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.c356
1 files changed, 324 insertions, 32 deletions
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index f56ffef4defa..a34ed49e0356 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -37,13 +37,18 @@
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>
42#include <asm/firmware.h>
40 43
41#ifdef CONFIG_PPC64 44#ifdef CONFIG_PPC64
42#include <asm/hvcall.h> 45#include <asm/hvcall.h>
43#include <asm/paca.h> 46#include <asm/paca.h>
47#include <asm/iseries/it_lp_reg_save.h>
44#endif 48#endif
45 49
46#include "nonstdio.h" 50#include "nonstdio.h"
51#include "dis-asm.h"
47 52
48#define scanhex xmon_scanhex 53#define scanhex xmon_scanhex
49#define skipbl xmon_skipbl 54#define skipbl xmon_skipbl
@@ -107,7 +112,6 @@ static int bsesc(void);
107static void dump(void); 112static void dump(void);
108static void prdump(unsigned long, long); 113static void prdump(unsigned long, long);
109static int ppc_inst_dump(unsigned long, long, int); 114static int ppc_inst_dump(unsigned long, long, int);
110void print_address(unsigned long);
111static void backtrace(struct pt_regs *); 115static void backtrace(struct pt_regs *);
112static void excprint(struct pt_regs *); 116static void excprint(struct pt_regs *);
113static void prregs(struct pt_regs *); 117static void prregs(struct pt_regs *);
@@ -147,9 +151,9 @@ static void xmon_print_symbol(unsigned long address, const char *mid,
147 const char *after); 151 const char *after);
148static const char *getvecname(unsigned long vec); 152static const char *getvecname(unsigned long vec);
149 153
150int xmon_no_auto_backtrace; 154static int do_spu_cmd(void);
151 155
152extern int print_insn_powerpc(unsigned long, unsigned long, int); 156int xmon_no_auto_backtrace;
153 157
154extern void xmon_enter(void); 158extern void xmon_enter(void);
155extern void xmon_leave(void); 159extern void xmon_leave(void);
@@ -209,8 +213,15 @@ 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_SPU_BASE
218" ss stop execution on all spus\n\
219 sr restore execution on stopped spus\n\
220 sf # dump spu fields for spu # (in hex)\n\
221 sd # dump spu local store for spu # (in hex)\
222 sdi # disassemble spu local store for spu # (in hex)\n"
223#endif
224" S print special registers\n\
214 t print backtrace\n\ 225 t print backtrace\n\
215 x exit monitor and recover\n\ 226 x exit monitor and recover\n\
216 X exit monitor and dont recover\n" 227 X exit monitor and dont recover\n"
@@ -518,6 +529,7 @@ int xmon(struct pt_regs *excp)
518 xmon_save_regs(&regs); 529 xmon_save_regs(&regs);
519 excp = &regs; 530 excp = &regs;
520 } 531 }
532
521 return xmon_core(excp, 0); 533 return xmon_core(excp, 0);
522} 534}
523EXPORT_SYMBOL(xmon); 535EXPORT_SYMBOL(xmon);
@@ -809,6 +821,8 @@ cmds(struct pt_regs *excp)
809 cacheflush(); 821 cacheflush();
810 break; 822 break;
811 case 's': 823 case 's':
824 if (do_spu_cmd() == 0)
825 break;
812 if (do_step(excp)) 826 if (do_step(excp))
813 return cmd; 827 return cmd;
814 break; 828 break;
@@ -1555,11 +1569,6 @@ void super_regs(void)
1555{ 1569{
1556 int cmd; 1570 int cmd;
1557 unsigned long val; 1571 unsigned long val;
1558#ifdef CONFIG_PPC_ISERIES
1559 struct paca_struct *ptrPaca = NULL;
1560 struct lppaca *ptrLpPaca = NULL;
1561 struct ItLpRegSave *ptrLpRegSave = NULL;
1562#endif
1563 1572
1564 cmd = skipbl(); 1573 cmd = skipbl();
1565 if (cmd == '\n') { 1574 if (cmd == '\n') {
@@ -1576,26 +1585,32 @@ void super_regs(void)
1576 printf("sp = "REG" sprg3= "REG"\n", sp, mfspr(SPRN_SPRG3)); 1585 printf("sp = "REG" sprg3= "REG"\n", sp, mfspr(SPRN_SPRG3));
1577 printf("toc = "REG" dar = "REG"\n", toc, mfspr(SPRN_DAR)); 1586 printf("toc = "REG" dar = "REG"\n", toc, mfspr(SPRN_DAR));
1578#ifdef CONFIG_PPC_ISERIES 1587#ifdef CONFIG_PPC_ISERIES
1579 // Dump out relevant Paca data areas. 1588 if (firmware_has_feature(FW_FEATURE_ISERIES)) {
1580 printf("Paca: \n"); 1589 struct paca_struct *ptrPaca;
1581 ptrPaca = get_paca(); 1590 struct lppaca *ptrLpPaca;
1582 1591 struct ItLpRegSave *ptrLpRegSave;
1583 printf(" Local Processor Control Area (LpPaca): \n"); 1592
1584 ptrLpPaca = ptrPaca->lppaca_ptr; 1593 /* Dump out relevant Paca data areas. */
1585 printf(" Saved Srr0=%.16lx Saved Srr1=%.16lx \n", 1594 printf("Paca: \n");
1586 ptrLpPaca->saved_srr0, ptrLpPaca->saved_srr1); 1595 ptrPaca = get_paca();
1587 printf(" Saved Gpr3=%.16lx Saved Gpr4=%.16lx \n", 1596
1588 ptrLpPaca->saved_gpr3, ptrLpPaca->saved_gpr4); 1597 printf(" Local Processor Control Area (LpPaca): \n");
1589 printf(" Saved Gpr5=%.16lx \n", ptrLpPaca->saved_gpr5); 1598 ptrLpPaca = ptrPaca->lppaca_ptr;
1590 1599 printf(" Saved Srr0=%.16lx Saved Srr1=%.16lx \n",
1591 printf(" Local Processor Register Save Area (LpRegSave): \n"); 1600 ptrLpPaca->saved_srr0, ptrLpPaca->saved_srr1);
1592 ptrLpRegSave = ptrPaca->reg_save_ptr; 1601 printf(" Saved Gpr3=%.16lx Saved Gpr4=%.16lx \n",
1593 printf(" Saved Sprg0=%.16lx Saved Sprg1=%.16lx \n", 1602 ptrLpPaca->saved_gpr3, ptrLpPaca->saved_gpr4);
1594 ptrLpRegSave->xSPRG0, ptrLpRegSave->xSPRG0); 1603 printf(" Saved Gpr5=%.16lx \n", ptrLpPaca->saved_gpr5);
1595 printf(" Saved Sprg2=%.16lx Saved Sprg3=%.16lx \n", 1604
1596 ptrLpRegSave->xSPRG2, ptrLpRegSave->xSPRG3); 1605 printf(" Local Processor Register Save Area (LpRegSave): \n");
1597 printf(" Saved Msr =%.16lx Saved Nia =%.16lx \n", 1606 ptrLpRegSave = ptrPaca->reg_save_ptr;
1598 ptrLpRegSave->xMSR, ptrLpRegSave->xNIA); 1607 printf(" Saved Sprg0=%.16lx Saved Sprg1=%.16lx \n",
1608 ptrLpRegSave->xSPRG0, ptrLpRegSave->xSPRG0);
1609 printf(" Saved Sprg2=%.16lx Saved Sprg3=%.16lx \n",
1610 ptrLpRegSave->xSPRG2, ptrLpRegSave->xSPRG3);
1611 printf(" Saved Msr =%.16lx Saved Nia =%.16lx \n",
1612 ptrLpRegSave->xMSR, ptrLpRegSave->xNIA);
1613 }
1599#endif 1614#endif
1600 1615
1601 return; 1616 return;
@@ -2053,8 +2068,11 @@ prdump(unsigned long adrs, long ndump)
2053 } 2068 }
2054} 2069}
2055 2070
2071typedef int (*instruction_dump_func)(unsigned long inst, unsigned long addr);
2072
2056int 2073int
2057ppc_inst_dump(unsigned long adr, long count, int praddr) 2074generic_inst_dump(unsigned long adr, long count, int praddr,
2075 instruction_dump_func dump_func)
2058{ 2076{
2059 int nr, dotted; 2077 int nr, dotted;
2060 unsigned long first_adr; 2078 unsigned long first_adr;
@@ -2084,12 +2102,18 @@ ppc_inst_dump(unsigned long adr, long count, int praddr)
2084 if (praddr) 2102 if (praddr)
2085 printf(REG" %.8x", adr, inst); 2103 printf(REG" %.8x", adr, inst);
2086 printf("\t"); 2104 printf("\t");
2087 print_insn_powerpc(inst, adr, 0); /* always returns 4 */ 2105 dump_func(inst, adr);
2088 printf("\n"); 2106 printf("\n");
2089 } 2107 }
2090 return adr - first_adr; 2108 return adr - first_adr;
2091} 2109}
2092 2110
2111int
2112ppc_inst_dump(unsigned long adr, long count, int praddr)
2113{
2114 return generic_inst_dump(adr, count, praddr, print_insn_powerpc);
2115}
2116
2093void 2117void
2094print_address(unsigned long addr) 2118print_address(unsigned long addr)
2095{ 2119{
@@ -2557,6 +2581,10 @@ void dump_segments(void)
2557 2581
2558void xmon_init(int enable) 2582void xmon_init(int enable)
2559{ 2583{
2584#ifdef CONFIG_PPC_ISERIES
2585 if (firmware_has_feature(FW_FEATURE_ISERIES))
2586 return;
2587#endif
2560 if (enable) { 2588 if (enable) {
2561 __debugger = xmon; 2589 __debugger = xmon;
2562 __debugger_ipi = xmon_ipi; 2590 __debugger_ipi = xmon_ipi;
@@ -2594,6 +2622,10 @@ static struct sysrq_key_op sysrq_xmon_op =
2594 2622
2595static int __init setup_xmon_sysrq(void) 2623static int __init setup_xmon_sysrq(void)
2596{ 2624{
2625#ifdef CONFIG_PPC_ISERIES
2626 if (firmware_has_feature(FW_FEATURE_ISERIES))
2627 return 0;
2628#endif
2597 register_sysrq_key('x', &sysrq_xmon_op); 2629 register_sysrq_key('x', &sysrq_xmon_op);
2598 return 0; 2630 return 0;
2599} 2631}
@@ -2630,3 +2662,263 @@ void __init xmon_setup(void)
2630 if (xmon_early) 2662 if (xmon_early)
2631 debugger(NULL); 2663 debugger(NULL);
2632} 2664}
2665
2666#ifdef CONFIG_SPU_BASE
2667
2668struct spu_info {
2669 struct spu *spu;
2670 u64 saved_mfc_sr1_RW;
2671 u32 saved_spu_runcntl_RW;
2672 unsigned long dump_addr;
2673 u8 stopped_ok;
2674};
2675
2676#define XMON_NUM_SPUS 16 /* Enough for current hardware */
2677
2678static struct spu_info spu_info[XMON_NUM_SPUS];
2679
2680void xmon_register_spus(struct list_head *list)
2681{
2682 struct spu *spu;
2683
2684 list_for_each_entry(spu, list, full_list) {
2685 if (spu->number >= XMON_NUM_SPUS) {
2686 WARN_ON(1);
2687 continue;
2688 }
2689
2690 spu_info[spu->number].spu = spu;
2691 spu_info[spu->number].stopped_ok = 0;
2692 spu_info[spu->number].dump_addr = (unsigned long)
2693 spu_info[spu->number].spu->local_store;
2694 }
2695}
2696
2697static void stop_spus(void)
2698{
2699 struct spu *spu;
2700 int i;
2701 u64 tmp;
2702
2703 for (i = 0; i < XMON_NUM_SPUS; i++) {
2704 if (!spu_info[i].spu)
2705 continue;
2706
2707 if (setjmp(bus_error_jmp) == 0) {
2708 catch_memory_errors = 1;
2709 sync();
2710
2711 spu = spu_info[i].spu;
2712
2713 spu_info[i].saved_spu_runcntl_RW =
2714 in_be32(&spu->problem->spu_runcntl_RW);
2715
2716 tmp = spu_mfc_sr1_get(spu);
2717 spu_info[i].saved_mfc_sr1_RW = tmp;
2718
2719 tmp &= ~MFC_STATE1_MASTER_RUN_CONTROL_MASK;
2720 spu_mfc_sr1_set(spu, tmp);
2721
2722 sync();
2723 __delay(200);
2724
2725 spu_info[i].stopped_ok = 1;
2726
2727 printf("Stopped spu %.2d (was %s)\n", i,
2728 spu_info[i].saved_spu_runcntl_RW ?
2729 "running" : "stopped");
2730 } else {
2731 catch_memory_errors = 0;
2732 printf("*** Error stopping spu %.2d\n", i);
2733 }
2734 catch_memory_errors = 0;
2735 }
2736}
2737
2738static void restart_spus(void)
2739{
2740 struct spu *spu;
2741 int i;
2742
2743 for (i = 0; i < XMON_NUM_SPUS; i++) {
2744 if (!spu_info[i].spu)
2745 continue;
2746
2747 if (!spu_info[i].stopped_ok) {
2748 printf("*** Error, spu %d was not successfully stopped"
2749 ", not restarting\n", i);
2750 continue;
2751 }
2752
2753 if (setjmp(bus_error_jmp) == 0) {
2754 catch_memory_errors = 1;
2755 sync();
2756
2757 spu = spu_info[i].spu;
2758 spu_mfc_sr1_set(spu, spu_info[i].saved_mfc_sr1_RW);
2759 out_be32(&spu->problem->spu_runcntl_RW,
2760 spu_info[i].saved_spu_runcntl_RW);
2761
2762 sync();
2763 __delay(200);
2764
2765 printf("Restarted spu %.2d\n", i);
2766 } else {
2767 catch_memory_errors = 0;
2768 printf("*** Error restarting spu %.2d\n", i);
2769 }
2770 catch_memory_errors = 0;
2771 }
2772}
2773
2774#define DUMP_WIDTH 23
2775#define DUMP_VALUE(format, field, value) \
2776do { \
2777 if (setjmp(bus_error_jmp) == 0) { \
2778 catch_memory_errors = 1; \
2779 sync(); \
2780 printf(" %-*s = "format"\n", DUMP_WIDTH, \
2781 #field, value); \
2782 sync(); \
2783 __delay(200); \
2784 } else { \
2785 catch_memory_errors = 0; \
2786 printf(" %-*s = *** Error reading field.\n", \
2787 DUMP_WIDTH, #field); \
2788 } \
2789 catch_memory_errors = 0; \
2790} while (0)
2791
2792#define DUMP_FIELD(obj, format, field) \
2793 DUMP_VALUE(format, field, obj->field)
2794
2795static void dump_spu_fields(struct spu *spu)
2796{
2797 printf("Dumping spu fields at address %p:\n", spu);
2798
2799 DUMP_FIELD(spu, "0x%x", number);
2800 DUMP_FIELD(spu, "%s", name);
2801 DUMP_FIELD(spu, "0x%lx", local_store_phys);
2802 DUMP_FIELD(spu, "0x%p", local_store);
2803 DUMP_FIELD(spu, "0x%lx", ls_size);
2804 DUMP_FIELD(spu, "0x%x", node);
2805 DUMP_FIELD(spu, "0x%lx", flags);
2806 DUMP_FIELD(spu, "0x%lx", dar);
2807 DUMP_FIELD(spu, "0x%lx", dsisr);
2808 DUMP_FIELD(spu, "%d", class_0_pending);
2809 DUMP_FIELD(spu, "0x%lx", irqs[0]);
2810 DUMP_FIELD(spu, "0x%lx", irqs[1]);
2811 DUMP_FIELD(spu, "0x%lx", irqs[2]);
2812 DUMP_FIELD(spu, "0x%x", slb_replace);
2813 DUMP_FIELD(spu, "%d", pid);
2814 DUMP_FIELD(spu, "%d", prio);
2815 DUMP_FIELD(spu, "0x%p", mm);
2816 DUMP_FIELD(spu, "0x%p", ctx);
2817 DUMP_FIELD(spu, "0x%p", rq);
2818 DUMP_FIELD(spu, "0x%p", timestamp);
2819 DUMP_FIELD(spu, "0x%lx", problem_phys);
2820 DUMP_FIELD(spu, "0x%p", problem);
2821 DUMP_VALUE("0x%x", problem->spu_runcntl_RW,
2822 in_be32(&spu->problem->spu_runcntl_RW));
2823 DUMP_VALUE("0x%x", problem->spu_status_R,
2824 in_be32(&spu->problem->spu_status_R));
2825 DUMP_VALUE("0x%x", problem->spu_npc_RW,
2826 in_be32(&spu->problem->spu_npc_RW));
2827 DUMP_FIELD(spu, "0x%p", priv2);
2828 DUMP_FIELD(spu, "0x%p", pdata);
2829}
2830
2831int
2832spu_inst_dump(unsigned long adr, long count, int praddr)
2833{
2834 return generic_inst_dump(adr, count, praddr, print_insn_spu);
2835}
2836
2837static void dump_spu_ls(unsigned long num, int subcmd)
2838{
2839 unsigned long offset, addr, ls_addr;
2840
2841 if (setjmp(bus_error_jmp) == 0) {
2842 catch_memory_errors = 1;
2843 sync();
2844 ls_addr = (unsigned long)spu_info[num].spu->local_store;
2845 sync();
2846 __delay(200);
2847 } else {
2848 catch_memory_errors = 0;
2849 printf("*** Error: accessing spu info for spu %d\n", num);
2850 return;
2851 }
2852 catch_memory_errors = 0;
2853
2854 if (scanhex(&offset))
2855 addr = ls_addr + offset;
2856 else
2857 addr = spu_info[num].dump_addr;
2858
2859 if (addr >= ls_addr + LS_SIZE) {
2860 printf("*** Error: address outside of local store\n");
2861 return;
2862 }
2863
2864 switch (subcmd) {
2865 case 'i':
2866 addr += spu_inst_dump(addr, 16, 1);
2867 last_cmd = "sdi\n";
2868 break;
2869 default:
2870 prdump(addr, 64);
2871 addr += 64;
2872 last_cmd = "sd\n";
2873 break;
2874 }
2875
2876 spu_info[num].dump_addr = addr;
2877}
2878
2879static int do_spu_cmd(void)
2880{
2881 static unsigned long num = 0;
2882 int cmd, subcmd = 0;
2883
2884 cmd = inchar();
2885 switch (cmd) {
2886 case 's':
2887 stop_spus();
2888 break;
2889 case 'r':
2890 restart_spus();
2891 break;
2892 case 'd':
2893 subcmd = inchar();
2894 if (isxdigit(subcmd) || subcmd == '\n')
2895 termch = subcmd;
2896 case 'f':
2897 scanhex(&num);
2898 if (num >= XMON_NUM_SPUS || !spu_info[num].spu) {
2899 printf("*** Error: invalid spu number\n");
2900 return 0;
2901 }
2902
2903 switch (cmd) {
2904 case 'f':
2905 dump_spu_fields(spu_info[num].spu);
2906 break;
2907 default:
2908 dump_spu_ls(num, subcmd);
2909 break;
2910 }
2911
2912 break;
2913 default:
2914 return -1;
2915 }
2916
2917 return 0;
2918}
2919#else /* ! CONFIG_SPU_BASE */
2920static int do_spu_cmd(void)
2921{
2922 return -1;
2923}
2924#endif