x86: remove pointless comments
[linux-2.6.git] / arch / powerpc / xmon / xmon.c
1 /*
2  * Routines providing a simple monitor for use on the PowerMac.
3  *
4  * Copyright (C) 1996-2005 Paul Mackerras.
5  * Copyright (C) 2001 PPC64 Team, IBM Corp
6  * Copyrignt (C) 2006 Michael Ellerman, IBM Corp
7  *
8  *      This program is free software; you can redistribute it and/or
9  *      modify it under the terms of the GNU General Public License
10  *      as published by the Free Software Foundation; either version
11  *      2 of the License, or (at your option) any later version.
12  */
13 #include <linux/errno.h>
14 #include <linux/sched.h>
15 #include <linux/smp.h>
16 #include <linux/mm.h>
17 #include <linux/reboot.h>
18 #include <linux/delay.h>
19 #include <linux/kallsyms.h>
20 #include <linux/cpumask.h>
21 #include <linux/module.h>
22 #include <linux/sysrq.h>
23 #include <linux/interrupt.h>
24 #include <linux/irq.h>
25 #include <linux/bug.h>
26
27 #include <asm/ptrace.h>
28 #include <asm/string.h>
29 #include <asm/prom.h>
30 #include <asm/machdep.h>
31 #include <asm/xmon.h>
32 #include <asm/processor.h>
33 #include <asm/pgtable.h>
34 #include <asm/mmu.h>
35 #include <asm/mmu_context.h>
36 #include <asm/cputable.h>
37 #include <asm/rtas.h>
38 #include <asm/sstep.h>
39 #include <asm/irq_regs.h>
40 #include <asm/spu.h>
41 #include <asm/spu_priv1.h>
42 #include <asm/firmware.h>
43 #include <asm/setjmp.h>
44
45 #ifdef CONFIG_PPC64
46 #include <asm/hvcall.h>
47 #include <asm/paca.h>
48 #include <asm/iseries/it_lp_reg_save.h>
49 #endif
50
51 #include "nonstdio.h"
52 #include "dis-asm.h"
53
54 #define scanhex xmon_scanhex
55 #define skipbl  xmon_skipbl
56
57 #ifdef CONFIG_SMP
58 cpumask_t cpus_in_xmon = CPU_MASK_NONE;
59 static unsigned long xmon_taken = 1;
60 static int xmon_owner;
61 static int xmon_gate;
62 #endif /* CONFIG_SMP */
63
64 static unsigned long in_xmon = 0;
65
66 static unsigned long adrs;
67 static int size = 1;
68 #define MAX_DUMP (128 * 1024)
69 static unsigned long ndump = 64;
70 static unsigned long nidump = 16;
71 static unsigned long ncsum = 4096;
72 static int termch;
73 static char tmpstr[128];
74
75 static long bus_error_jmp[JMP_BUF_LEN];
76 static int catch_memory_errors;
77 static long *xmon_fault_jmp[NR_CPUS];
78
79 /* Breakpoint stuff */
80 struct bpt {
81         unsigned long   address;
82         unsigned int    instr[2];
83         atomic_t        ref_count;
84         int             enabled;
85         unsigned long   pad;
86 };
87
88 /* Bits in bpt.enabled */
89 #define BP_IABR_TE      1               /* IABR translation enabled */
90 #define BP_IABR         2
91 #define BP_TRAP         8
92 #define BP_DABR         0x10
93
94 #define NBPTS   256
95 static struct bpt bpts[NBPTS];
96 static struct bpt dabr;
97 static struct bpt *iabr;
98 static unsigned bpinstr = 0x7fe00008;   /* trap */
99
100 #define BP_NUM(bp)      ((bp) - bpts + 1)
101
102 /* Prototypes */
103 static int cmds(struct pt_regs *);
104 static int mread(unsigned long, void *, int);
105 static int mwrite(unsigned long, void *, int);
106 static int handle_fault(struct pt_regs *);
107 static void byterev(unsigned char *, int);
108 static void memex(void);
109 static int bsesc(void);
110 static void dump(void);
111 static void prdump(unsigned long, long);
112 static int ppc_inst_dump(unsigned long, long, int);
113 static void backtrace(struct pt_regs *);
114 static void excprint(struct pt_regs *);
115 static void prregs(struct pt_regs *);
116 static void memops(int);
117 static void memlocate(void);
118 static void memzcan(void);
119 static void memdiffs(unsigned char *, unsigned char *, unsigned, unsigned);
120 int skipbl(void);
121 int scanhex(unsigned long *valp);
122 static void scannl(void);
123 static int hexdigit(int);
124 void getstring(char *, int);
125 static void flush_input(void);
126 static int inchar(void);
127 static void take_input(char *);
128 static unsigned long read_spr(int);
129 static void write_spr(int, unsigned long);
130 static void super_regs(void);
131 static void remove_bpts(void);
132 static void insert_bpts(void);
133 static void remove_cpu_bpts(void);
134 static void insert_cpu_bpts(void);
135 static struct bpt *at_breakpoint(unsigned long pc);
136 static struct bpt *in_breakpoint_table(unsigned long pc, unsigned long *offp);
137 static int  do_step(struct pt_regs *);
138 static void bpt_cmds(void);
139 static void cacheflush(void);
140 static int  cpu_cmd(void);
141 static void csum(void);
142 static void bootcmds(void);
143 static void proccall(void);
144 void dump_segments(void);
145 static void symbol_lookup(void);
146 static void xmon_show_stack(unsigned long sp, unsigned long lr,
147                             unsigned long pc);
148 static void xmon_print_symbol(unsigned long address, const char *mid,
149                               const char *after);
150 static const char *getvecname(unsigned long vec);
151
152 static int do_spu_cmd(void);
153
154 #ifdef CONFIG_44x
155 static void dump_tlb_44x(void);
156 #endif
157
158 int xmon_no_auto_backtrace;
159
160 extern void xmon_enter(void);
161 extern void xmon_leave(void);
162
163 extern void xmon_save_regs(struct pt_regs *);
164
165 #ifdef CONFIG_PPC64
166 #define REG             "%.16lx"
167 #define REGS_PER_LINE   4
168 #define LAST_VOLATILE   13
169 #else
170 #define REG             "%.8lx"
171 #define REGS_PER_LINE   8
172 #define LAST_VOLATILE   12
173 #endif
174
175 #define GETWORD(v)      (((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
176
177 #define isxdigit(c)     (('0' <= (c) && (c) <= '9') \
178                          || ('a' <= (c) && (c) <= 'f') \
179                          || ('A' <= (c) && (c) <= 'F'))
180 #define isalnum(c)      (('0' <= (c) && (c) <= '9') \
181                          || ('a' <= (c) && (c) <= 'z') \
182                          || ('A' <= (c) && (c) <= 'Z'))
183 #define isspace(c)      (c == ' ' || c == '\t' || c == 10 || c == 13 || c == 0)
184
185 static char *help_string = "\
186 Commands:\n\
187   b     show breakpoints\n\
188   bd    set data breakpoint\n\
189   bi    set instruction breakpoint\n\
190   bc    clear breakpoint\n"
191 #ifdef CONFIG_SMP
192   "\
193   c     print cpus stopped in xmon\n\
194   c#    try to switch to cpu number h (in hex)\n"
195 #endif
196   "\
197   C     checksum\n\
198   d     dump bytes\n\
199   di    dump instructions\n\
200   df    dump float values\n\
201   dd    dump double values\n\
202   dr    dump stream of raw bytes\n\
203   e     print exception information\n\
204   f     flush cache\n\
205   la    lookup symbol+offset of specified address\n\
206   ls    lookup address of specified symbol\n\
207   m     examine/change memory\n\
208   mm    move a block of memory\n\
209   ms    set a block of memory\n\
210   md    compare two blocks of memory\n\
211   ml    locate a block of memory\n\
212   mz    zero a block of memory\n\
213   mi    show information about memory allocation\n\
214   p     call a procedure\n\
215   r     print registers\n\
216   s     single step\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)\n\
222   sdi # disassemble spu local store for spu # (in hex)\n"
223 #endif
224 "  S    print special registers\n\
225   t     print backtrace\n\
226   x     exit monitor and recover\n\
227   X     exit monitor and dont recover\n"
228 #ifdef CONFIG_PPC64
229 "  u    dump segment table or SLB\n"
230 #endif
231 #ifdef CONFIG_PPC_STD_MMU_32
232 "  u    dump segment registers\n"
233 #endif
234 #ifdef CONFIG_44x
235 "  u    dump TLB\n"
236 #endif
237 "  ?    help\n"
238 "  zr   reboot\n\
239   zh    halt\n"
240 ;
241
242 static struct pt_regs *xmon_regs;
243
244 static inline void sync(void)
245 {
246         asm volatile("sync; isync");
247 }
248
249 static inline void store_inst(void *p)
250 {
251         asm volatile ("dcbst 0,%0; sync; icbi 0,%0; isync" : : "r" (p));
252 }
253
254 static inline void cflush(void *p)
255 {
256         asm volatile ("dcbf 0,%0; icbi 0,%0" : : "r" (p));
257 }
258
259 static inline void cinval(void *p)
260 {
261         asm volatile ("dcbi 0,%0; icbi 0,%0" : : "r" (p));
262 }
263
264 /*
265  * Disable surveillance (the service processor watchdog function)
266  * while we are in xmon.
267  * XXX we should re-enable it when we leave. :)
268  */
269 #define SURVEILLANCE_TOKEN      9000
270
271 static inline void disable_surveillance(void)
272 {
273 #ifdef CONFIG_PPC_PSERIES
274         /* Since this can't be a module, args should end up below 4GB. */
275         static struct rtas_args args;
276
277         /*
278          * At this point we have got all the cpus we can into
279          * xmon, so there is hopefully no other cpu calling RTAS
280          * at the moment, even though we don't take rtas.lock.
281          * If we did try to take rtas.lock there would be a
282          * real possibility of deadlock.
283          */
284         args.token = rtas_token("set-indicator");
285         if (args.token == RTAS_UNKNOWN_SERVICE)
286                 return;
287         args.nargs = 3;
288         args.nret = 1;
289         args.rets = &args.args[3];
290         args.args[0] = SURVEILLANCE_TOKEN;
291         args.args[1] = 0;
292         args.args[2] = 0;
293         enter_rtas(__pa(&args));
294 #endif /* CONFIG_PPC_PSERIES */
295 }
296
297 #ifdef CONFIG_SMP
298 static int xmon_speaker;
299
300 static void get_output_lock(void)
301 {
302         int me = smp_processor_id() + 0x100;
303         int last_speaker = 0, prev;
304         long timeout;
305
306         if (xmon_speaker == me)
307                 return;
308         for (;;) {
309                 if (xmon_speaker == 0) {
310                         last_speaker = cmpxchg(&xmon_speaker, 0, me);
311                         if (last_speaker == 0)
312                                 return;
313                 }
314                 timeout = 10000000;
315                 while (xmon_speaker == last_speaker) {
316                         if (--timeout > 0)
317                                 continue;
318                         /* hostile takeover */
319                         prev = cmpxchg(&xmon_speaker, last_speaker, me);
320                         if (prev == last_speaker)
321                                 return;
322                         break;
323                 }
324         }
325 }
326
327 static void release_output_lock(void)
328 {
329         xmon_speaker = 0;
330 }
331 #endif
332
333 static int xmon_core(struct pt_regs *regs, int fromipi)
334 {
335         int cmd = 0;
336         struct bpt *bp;
337         long recurse_jmp[JMP_BUF_LEN];
338         unsigned long offset;
339         unsigned long flags;
340 #ifdef CONFIG_SMP
341         int cpu;
342         int secondary;
343         unsigned long timeout;
344 #endif
345
346         local_irq_save(flags);
347
348         bp = in_breakpoint_table(regs->nip, &offset);
349         if (bp != NULL) {
350                 regs->nip = bp->address + offset;
351                 atomic_dec(&bp->ref_count);
352         }
353
354         remove_cpu_bpts();
355
356 #ifdef CONFIG_SMP
357         cpu = smp_processor_id();
358         if (cpu_isset(cpu, cpus_in_xmon)) {
359                 get_output_lock();
360                 excprint(regs);
361                 printf("cpu 0x%x: Exception %lx %s in xmon, "
362                        "returning to main loop\n",
363                        cpu, regs->trap, getvecname(TRAP(regs)));
364                 release_output_lock();
365                 longjmp(xmon_fault_jmp[cpu], 1);
366         }
367
368         if (setjmp(recurse_jmp) != 0) {
369                 if (!in_xmon || !xmon_gate) {
370                         get_output_lock();
371                         printf("xmon: WARNING: bad recursive fault "
372                                "on cpu 0x%x\n", cpu);
373                         release_output_lock();
374                         goto waiting;
375                 }
376                 secondary = !(xmon_taken && cpu == xmon_owner);
377                 goto cmdloop;
378         }
379
380         xmon_fault_jmp[cpu] = recurse_jmp;
381         cpu_set(cpu, cpus_in_xmon);
382
383         bp = NULL;
384         if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) == (MSR_IR|MSR_SF))
385                 bp = at_breakpoint(regs->nip);
386         if (bp || (regs->msr & MSR_RI) == 0)
387                 fromipi = 0;
388
389         if (!fromipi) {
390                 get_output_lock();
391                 excprint(regs);
392                 if (bp) {
393                         printf("cpu 0x%x stopped at breakpoint 0x%x (",
394                                cpu, BP_NUM(bp));
395                         xmon_print_symbol(regs->nip, " ", ")\n");
396                 }
397                 if ((regs->msr & MSR_RI) == 0)
398                         printf("WARNING: exception is not recoverable, "
399                                "can't continue\n");
400                 release_output_lock();
401         }
402
403  waiting:
404         secondary = 1;
405         while (secondary && !xmon_gate) {
406                 if (in_xmon == 0) {
407                         if (fromipi)
408                                 goto leave;
409                         secondary = test_and_set_bit(0, &in_xmon);
410                 }
411                 barrier();
412         }
413
414         if (!secondary && !xmon_gate) {
415                 /* we are the first cpu to come in */
416                 /* interrupt other cpu(s) */
417                 int ncpus = num_online_cpus();
418
419                 xmon_owner = cpu;
420                 mb();
421                 if (ncpus > 1) {
422                         smp_send_debugger_break(MSG_ALL_BUT_SELF);
423                         /* wait for other cpus to come in */
424                         for (timeout = 100000000; timeout != 0; --timeout) {
425                                 if (cpus_weight(cpus_in_xmon) >= ncpus)
426                                         break;
427                                 barrier();
428                         }
429                 }
430                 remove_bpts();
431                 disable_surveillance();
432                 /* for breakpoint or single step, print the current instr. */
433                 if (bp || TRAP(regs) == 0xd00)
434                         ppc_inst_dump(regs->nip, 1, 0);
435                 printf("enter ? for help\n");
436                 mb();
437                 xmon_gate = 1;
438                 barrier();
439         }
440
441  cmdloop:
442         while (in_xmon) {
443                 if (secondary) {
444                         if (cpu == xmon_owner) {
445                                 if (!test_and_set_bit(0, &xmon_taken)) {
446                                         secondary = 0;
447                                         continue;
448                                 }
449                                 /* missed it */
450                                 while (cpu == xmon_owner)
451                                         barrier();
452                         }
453                         barrier();
454                 } else {
455                         cmd = cmds(regs);
456                         if (cmd != 0) {
457                                 /* exiting xmon */
458                                 insert_bpts();
459                                 xmon_gate = 0;
460                                 wmb();
461                                 in_xmon = 0;
462                                 break;
463                         }
464                         /* have switched to some other cpu */
465                         secondary = 1;
466                 }
467         }
468  leave:
469         cpu_clear(cpu, cpus_in_xmon);
470         xmon_fault_jmp[cpu] = NULL;
471 #else
472         /* UP is simple... */
473         if (in_xmon) {
474                 printf("Exception %lx %s in xmon, returning to main loop\n",
475                        regs->trap, getvecname(TRAP(regs)));
476                 longjmp(xmon_fault_jmp[0], 1);
477         }
478         if (setjmp(recurse_jmp) == 0) {
479                 xmon_fault_jmp[0] = recurse_jmp;
480                 in_xmon = 1;
481
482                 excprint(regs);
483                 bp = at_breakpoint(regs->nip);
484                 if (bp) {
485                         printf("Stopped at breakpoint %x (", BP_NUM(bp));
486                         xmon_print_symbol(regs->nip, " ", ")\n");
487                 }
488                 if ((regs->msr & MSR_RI) == 0)
489                         printf("WARNING: exception is not recoverable, "
490                                "can't continue\n");
491                 remove_bpts();
492                 disable_surveillance();
493                 /* for breakpoint or single step, print the current instr. */
494                 if (bp || TRAP(regs) == 0xd00)
495                         ppc_inst_dump(regs->nip, 1, 0);
496                 printf("enter ? for help\n");
497         }
498
499         cmd = cmds(regs);
500
501         insert_bpts();
502         in_xmon = 0;
503 #endif
504
505         if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) == (MSR_IR|MSR_SF)) {
506                 bp = at_breakpoint(regs->nip);
507                 if (bp != NULL) {
508                         int stepped = emulate_step(regs, bp->instr[0]);
509                         if (stepped == 0) {
510                                 regs->nip = (unsigned long) &bp->instr[0];
511                                 atomic_inc(&bp->ref_count);
512                         } else if (stepped < 0) {
513                                 printf("Couldn't single-step %s instruction\n",
514                                     (IS_RFID(bp->instr[0])? "rfid": "mtmsrd"));
515                         }
516                 }
517         }
518
519         insert_cpu_bpts();
520
521         local_irq_restore(flags);
522
523         return cmd != 'X' && cmd != EOF;
524 }
525
526 int xmon(struct pt_regs *excp)
527 {
528         struct pt_regs regs;
529
530         if (excp == NULL) {
531                 xmon_save_regs(&regs);
532                 excp = &regs;
533         }
534
535         return xmon_core(excp, 0);
536 }
537 EXPORT_SYMBOL(xmon);
538
539 irqreturn_t xmon_irq(int irq, void *d)
540 {
541         unsigned long flags;
542         local_irq_save(flags);
543         printf("Keyboard interrupt\n");
544         xmon(get_irq_regs());
545         local_irq_restore(flags);
546         return IRQ_HANDLED;
547 }
548
549 static int xmon_bpt(struct pt_regs *regs)
550 {
551         struct bpt *bp;
552         unsigned long offset;
553
554         if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF))
555                 return 0;
556
557         /* Are we at the trap at bp->instr[1] for some bp? */
558         bp = in_breakpoint_table(regs->nip, &offset);
559         if (bp != NULL && offset == 4) {
560                 regs->nip = bp->address + 4;
561                 atomic_dec(&bp->ref_count);
562                 return 1;
563         }
564
565         /* Are we at a breakpoint? */
566         bp = at_breakpoint(regs->nip);
567         if (!bp)
568                 return 0;
569
570         xmon_core(regs, 0);
571
572         return 1;
573 }
574
575 static int xmon_sstep(struct pt_regs *regs)
576 {
577         if (user_mode(regs))
578                 return 0;
579         xmon_core(regs, 0);
580         return 1;
581 }
582
583 static int xmon_dabr_match(struct pt_regs *regs)
584 {
585         if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF))
586                 return 0;
587         if (dabr.enabled == 0)
588                 return 0;
589         xmon_core(regs, 0);
590         return 1;
591 }
592
593 static int xmon_iabr_match(struct pt_regs *regs)
594 {
595         if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF))
596                 return 0;
597         if (iabr == 0)
598                 return 0;
599         xmon_core(regs, 0);
600         return 1;
601 }
602
603 static int xmon_ipi(struct pt_regs *regs)
604 {
605 #ifdef CONFIG_SMP
606         if (in_xmon && !cpu_isset(smp_processor_id(), cpus_in_xmon))
607                 xmon_core(regs, 1);
608 #endif
609         return 0;
610 }
611
612 static int xmon_fault_handler(struct pt_regs *regs)
613 {
614         struct bpt *bp;
615         unsigned long offset;
616
617         if (in_xmon && catch_memory_errors)
618                 handle_fault(regs);     /* doesn't return */
619
620         if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) == (MSR_IR|MSR_SF)) {
621                 bp = in_breakpoint_table(regs->nip, &offset);
622                 if (bp != NULL) {
623                         regs->nip = bp->address + offset;
624                         atomic_dec(&bp->ref_count);
625                 }
626         }
627
628         return 0;
629 }
630
631 static struct bpt *at_breakpoint(unsigned long pc)
632 {
633         int i;
634         struct bpt *bp;
635
636         bp = bpts;
637         for (i = 0; i < NBPTS; ++i, ++bp)
638                 if (bp->enabled && pc == bp->address)
639                         return bp;
640         return NULL;
641 }
642
643 static struct bpt *in_breakpoint_table(unsigned long nip, unsigned long *offp)
644 {
645         unsigned long off;
646
647         off = nip - (unsigned long) bpts;
648         if (off >= sizeof(bpts))
649                 return NULL;
650         off %= sizeof(struct bpt);
651         if (off != offsetof(struct bpt, instr[0])
652             && off != offsetof(struct bpt, instr[1]))
653                 return NULL;
654         *offp = off - offsetof(struct bpt, instr[0]);
655         return (struct bpt *) (nip - off);
656 }
657
658 static struct bpt *new_breakpoint(unsigned long a)
659 {
660         struct bpt *bp;
661
662         a &= ~3UL;
663         bp = at_breakpoint(a);
664         if (bp)
665                 return bp;
666
667         for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
668                 if (!bp->enabled && atomic_read(&bp->ref_count) == 0) {
669                         bp->address = a;
670                         bp->instr[1] = bpinstr;
671                         store_inst(&bp->instr[1]);
672                         return bp;
673                 }
674         }
675
676         printf("Sorry, no free breakpoints.  Please clear one first.\n");
677         return NULL;
678 }
679
680 static void insert_bpts(void)
681 {
682         int i;
683         struct bpt *bp;
684
685         bp = bpts;
686         for (i = 0; i < NBPTS; ++i, ++bp) {
687                 if ((bp->enabled & (BP_TRAP|BP_IABR)) == 0)
688                         continue;
689                 if (mread(bp->address, &bp->instr[0], 4) != 4) {
690                         printf("Couldn't read instruction at %lx, "
691                                "disabling breakpoint there\n", bp->address);
692                         bp->enabled = 0;
693                         continue;
694                 }
695                 if (IS_MTMSRD(bp->instr[0]) || IS_RFID(bp->instr[0])) {
696                         printf("Breakpoint at %lx is on an mtmsrd or rfid "
697                                "instruction, disabling it\n", bp->address);
698                         bp->enabled = 0;
699                         continue;
700                 }
701                 store_inst(&bp->instr[0]);
702                 if (bp->enabled & BP_IABR)
703                         continue;
704                 if (mwrite(bp->address, &bpinstr, 4) != 4) {
705                         printf("Couldn't write instruction at %lx, "
706                                "disabling breakpoint there\n", bp->address);
707                         bp->enabled &= ~BP_TRAP;
708                         continue;
709                 }
710                 store_inst((void *)bp->address);
711         }
712 }
713
714 static void insert_cpu_bpts(void)
715 {
716         if (dabr.enabled)
717                 set_dabr(dabr.address | (dabr.enabled & 7));
718         if (iabr && cpu_has_feature(CPU_FTR_IABR))
719                 mtspr(SPRN_IABR, iabr->address
720                          | (iabr->enabled & (BP_IABR|BP_IABR_TE)));
721 }
722
723 static void remove_bpts(void)
724 {
725         int i;
726         struct bpt *bp;
727         unsigned instr;
728
729         bp = bpts;
730         for (i = 0; i < NBPTS; ++i, ++bp) {
731                 if ((bp->enabled & (BP_TRAP|BP_IABR)) != BP_TRAP)
732                         continue;
733                 if (mread(bp->address, &instr, 4) == 4
734                     && instr == bpinstr
735                     && mwrite(bp->address, &bp->instr, 4) != 4)
736                         printf("Couldn't remove breakpoint at %lx\n",
737                                bp->address);
738                 else
739                         store_inst((void *)bp->address);
740         }
741 }
742
743 static void remove_cpu_bpts(void)
744 {
745         set_dabr(0);
746         if (cpu_has_feature(CPU_FTR_IABR))
747                 mtspr(SPRN_IABR, 0);
748 }
749
750 /* Command interpreting routine */
751 static char *last_cmd;
752
753 static int
754 cmds(struct pt_regs *excp)
755 {
756         int cmd = 0;
757
758         last_cmd = NULL;
759         xmon_regs = excp;
760
761         if (!xmon_no_auto_backtrace) {
762                 xmon_no_auto_backtrace = 1;
763                 xmon_show_stack(excp->gpr[1], excp->link, excp->nip);
764         }
765
766         for(;;) {
767 #ifdef CONFIG_SMP
768                 printf("%x:", smp_processor_id());
769 #endif /* CONFIG_SMP */
770                 printf("mon> ");
771                 flush_input();
772                 termch = 0;
773                 cmd = skipbl();
774                 if( cmd == '\n' ) {
775                         if (last_cmd == NULL)
776                                 continue;
777                         take_input(last_cmd);
778                         last_cmd = NULL;
779                         cmd = inchar();
780                 }
781                 switch (cmd) {
782                 case 'm':
783                         cmd = inchar();
784                         switch (cmd) {
785                         case 'm':
786                         case 's':
787                         case 'd':
788                                 memops(cmd);
789                                 break;
790                         case 'l':
791                                 memlocate();
792                                 break;
793                         case 'z':
794                                 memzcan();
795                                 break;
796                         case 'i':
797                                 show_mem();
798                                 break;
799                         default:
800                                 termch = cmd;
801                                 memex();
802                         }
803                         break;
804                 case 'd':
805                         dump();
806                         break;
807                 case 'l':
808                         symbol_lookup();
809                         break;
810                 case 'r':
811                         prregs(excp);   /* print regs */
812                         break;
813                 case 'e':
814                         excprint(excp);
815                         break;
816                 case 'S':
817                         super_regs();
818                         break;
819                 case 't':
820                         backtrace(excp);
821                         break;
822                 case 'f':
823                         cacheflush();
824                         break;
825                 case 's':
826                         if (do_spu_cmd() == 0)
827                                 break;
828                         if (do_step(excp))
829                                 return cmd;
830                         break;
831                 case 'x':
832                 case 'X':
833                         return cmd;
834                 case EOF:
835                         printf(" <no input ...>\n");
836                         mdelay(2000);
837                         return cmd;
838                 case '?':
839                         xmon_puts(help_string);
840                         break;
841                 case 'b':
842                         bpt_cmds();
843                         break;
844                 case 'C':
845                         csum();
846                         break;
847                 case 'c':
848                         if (cpu_cmd())
849                                 return 0;
850                         break;
851                 case 'z':
852                         bootcmds();
853                         break;
854                 case 'p':
855                         proccall();
856                         break;
857 #ifdef CONFIG_PPC_STD_MMU
858                 case 'u':
859                         dump_segments();
860                         break;
861 #endif
862 #ifdef CONFIG_4xx
863                 case 'u':
864                         dump_tlb_44x();
865                         break;
866 #endif
867                 default:
868                         printf("Unrecognized command: ");
869                         do {
870                                 if (' ' < cmd && cmd <= '~')
871                                         putchar(cmd);
872                                 else
873                                         printf("\\x%x", cmd);
874                                 cmd = inchar();
875                         } while (cmd != '\n'); 
876                         printf(" (type ? for help)\n");
877                         break;
878                 }
879         }
880 }
881
882 /*
883  * Step a single instruction.
884  * Some instructions we emulate, others we execute with MSR_SE set.
885  */
886 static int do_step(struct pt_regs *regs)
887 {
888         unsigned int instr;
889         int stepped;
890
891         /* check we are in 64-bit kernel mode, translation enabled */
892         if ((regs->msr & (MSR_SF|MSR_PR|MSR_IR)) == (MSR_SF|MSR_IR)) {
893                 if (mread(regs->nip, &instr, 4) == 4) {
894                         stepped = emulate_step(regs, instr);
895                         if (stepped < 0) {
896                                 printf("Couldn't single-step %s instruction\n",
897                                        (IS_RFID(instr)? "rfid": "mtmsrd"));
898                                 return 0;
899                         }
900                         if (stepped > 0) {
901                                 regs->trap = 0xd00 | (regs->trap & 1);
902                                 printf("stepped to ");
903                                 xmon_print_symbol(regs->nip, " ", "\n");
904                                 ppc_inst_dump(regs->nip, 1, 0);
905                                 return 0;
906                         }
907                 }
908         }
909         regs->msr |= MSR_SE;
910         return 1;
911 }
912
913 static void bootcmds(void)
914 {
915         int cmd;
916
917         cmd = inchar();
918         if (cmd == 'r')
919                 ppc_md.restart(NULL);
920         else if (cmd == 'h')
921                 ppc_md.halt();
922         else if (cmd == 'p')
923                 ppc_md.power_off();
924 }
925
926 static int cpu_cmd(void)
927 {
928 #ifdef CONFIG_SMP
929         unsigned long cpu;
930         int timeout;
931         int count;
932
933         if (!scanhex(&cpu)) {
934                 /* print cpus waiting or in xmon */
935                 printf("cpus stopped:");
936                 count = 0;
937                 for (cpu = 0; cpu < NR_CPUS; ++cpu) {
938                         if (cpu_isset(cpu, cpus_in_xmon)) {
939                                 if (count == 0)
940                                         printf(" %x", cpu);
941                                 ++count;
942                         } else {
943                                 if (count > 1)
944                                         printf("-%x", cpu - 1);
945                                 count = 0;
946                         }
947                 }
948                 if (count > 1)
949                         printf("-%x", NR_CPUS - 1);
950                 printf("\n");
951                 return 0;
952         }
953         /* try to switch to cpu specified */
954         if (!cpu_isset(cpu, cpus_in_xmon)) {
955                 printf("cpu 0x%x isn't in xmon\n", cpu);
956                 return 0;
957         }
958         xmon_taken = 0;
959         mb();
960         xmon_owner = cpu;
961         timeout = 10000000;
962         while (!xmon_taken) {
963                 if (--timeout == 0) {
964                         if (test_and_set_bit(0, &xmon_taken))
965                                 break;
966                         /* take control back */
967                         mb();
968                         xmon_owner = smp_processor_id();
969                         printf("cpu %u didn't take control\n", cpu);
970                         return 0;
971                 }
972                 barrier();
973         }
974         return 1;
975 #else
976         return 0;
977 #endif /* CONFIG_SMP */
978 }
979
980 static unsigned short fcstab[256] = {
981         0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
982         0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
983         0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
984         0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
985         0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
986         0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
987         0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
988         0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
989         0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
990         0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
991         0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
992         0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
993         0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
994         0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
995         0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
996         0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
997         0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
998         0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
999         0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
1000         0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
1001         0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
1002         0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
1003         0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
1004         0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
1005         0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
1006         0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
1007         0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
1008         0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
1009         0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
1010         0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
1011         0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
1012         0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
1013 };
1014
1015 #define FCS(fcs, c)     (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
1016
1017 static void
1018 csum(void)
1019 {
1020         unsigned int i;
1021         unsigned short fcs;
1022         unsigned char v;
1023
1024         if (!scanhex(&adrs))
1025                 return;
1026         if (!scanhex(&ncsum))
1027                 return;
1028         fcs = 0xffff;
1029         for (i = 0; i < ncsum; ++i) {
1030                 if (mread(adrs+i, &v, 1) == 0) {
1031                         printf("csum stopped at %x\n", adrs+i);
1032                         break;
1033                 }
1034                 fcs = FCS(fcs, v);
1035         }
1036         printf("%x\n", fcs);
1037 }
1038
1039 /*
1040  * Check if this is a suitable place to put a breakpoint.
1041  */
1042 static long check_bp_loc(unsigned long addr)
1043 {
1044         unsigned int instr;
1045
1046         addr &= ~3;
1047         if (!is_kernel_addr(addr)) {
1048                 printf("Breakpoints may only be placed at kernel addresses\n");
1049                 return 0;
1050         }
1051         if (!mread(addr, &instr, sizeof(instr))) {
1052                 printf("Can't read instruction at address %lx\n", addr);
1053                 return 0;
1054         }
1055         if (IS_MTMSRD(instr) || IS_RFID(instr)) {
1056                 printf("Breakpoints may not be placed on mtmsrd or rfid "
1057                        "instructions\n");
1058                 return 0;
1059         }
1060         return 1;
1061 }
1062
1063 static char *breakpoint_help_string = 
1064     "Breakpoint command usage:\n"
1065     "b                show breakpoints\n"
1066     "b <addr> [cnt]   set breakpoint at given instr addr\n"
1067     "bc               clear all breakpoints\n"
1068     "bc <n/addr>      clear breakpoint number n or at addr\n"
1069     "bi <addr> [cnt]  set hardware instr breakpoint (POWER3/RS64 only)\n"
1070     "bd <addr> [cnt]  set hardware data breakpoint\n"
1071     "";
1072
1073 static void
1074 bpt_cmds(void)
1075 {
1076         int cmd;
1077         unsigned long a;
1078         int mode, i;
1079         struct bpt *bp;
1080         const char badaddr[] = "Only kernel addresses are permitted "
1081                 "for breakpoints\n";
1082
1083         cmd = inchar();
1084         switch (cmd) {
1085 #ifndef CONFIG_8xx
1086         case 'd':       /* bd - hardware data breakpoint */
1087                 mode = 7;
1088                 cmd = inchar();
1089                 if (cmd == 'r')
1090                         mode = 5;
1091                 else if (cmd == 'w')
1092                         mode = 6;
1093                 else
1094                         termch = cmd;
1095                 dabr.address = 0;
1096                 dabr.enabled = 0;
1097                 if (scanhex(&dabr.address)) {
1098                         if (!is_kernel_addr(dabr.address)) {
1099                                 printf(badaddr);
1100                                 break;
1101                         }
1102                         dabr.address &= ~7;
1103                         dabr.enabled = mode | BP_DABR;
1104                 }
1105                 break;
1106
1107         case 'i':       /* bi - hardware instr breakpoint */
1108                 if (!cpu_has_feature(CPU_FTR_IABR)) {
1109                         printf("Hardware instruction breakpoint "
1110                                "not supported on this cpu\n");
1111                         break;
1112                 }
1113                 if (iabr) {
1114                         iabr->enabled &= ~(BP_IABR | BP_IABR_TE);
1115                         iabr = NULL;
1116                 }
1117                 if (!scanhex(&a))
1118                         break;
1119                 if (!check_bp_loc(a))
1120                         break;
1121                 bp = new_breakpoint(a);
1122                 if (bp != NULL) {
1123                         bp->enabled |= BP_IABR | BP_IABR_TE;
1124                         iabr = bp;
1125                 }
1126                 break;
1127 #endif
1128
1129         case 'c':
1130                 if (!scanhex(&a)) {
1131                         /* clear all breakpoints */
1132                         for (i = 0; i < NBPTS; ++i)
1133                                 bpts[i].enabled = 0;
1134                         iabr = NULL;
1135                         dabr.enabled = 0;
1136                         printf("All breakpoints cleared\n");
1137                         break;
1138                 }
1139
1140                 if (a <= NBPTS && a >= 1) {
1141                         /* assume a breakpoint number */
1142                         bp = &bpts[a-1];        /* bp nums are 1 based */
1143                 } else {
1144                         /* assume a breakpoint address */
1145                         bp = at_breakpoint(a);
1146                         if (bp == 0) {
1147                                 printf("No breakpoint at %x\n", a);
1148                                 break;
1149                         }
1150                 }
1151
1152                 printf("Cleared breakpoint %x (", BP_NUM(bp));
1153                 xmon_print_symbol(bp->address, " ", ")\n");
1154                 bp->enabled = 0;
1155                 break;
1156
1157         default:
1158                 termch = cmd;
1159                 cmd = skipbl();
1160                 if (cmd == '?') {
1161                         printf(breakpoint_help_string);
1162                         break;
1163                 }
1164                 termch = cmd;
1165                 if (!scanhex(&a)) {
1166                         /* print all breakpoints */
1167                         printf("   type            address\n");
1168                         if (dabr.enabled) {
1169                                 printf("   data   "REG"  [", dabr.address);
1170                                 if (dabr.enabled & 1)
1171                                         printf("r");
1172                                 if (dabr.enabled & 2)
1173                                         printf("w");
1174                                 printf("]\n");
1175                         }
1176                         for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
1177                                 if (!bp->enabled)
1178                                         continue;
1179                                 printf("%2x %s   ", BP_NUM(bp),
1180                                     (bp->enabled & BP_IABR)? "inst": "trap");
1181                                 xmon_print_symbol(bp->address, "  ", "\n");
1182                         }
1183                         break;
1184                 }
1185
1186                 if (!check_bp_loc(a))
1187                         break;
1188                 bp = new_breakpoint(a);
1189                 if (bp != NULL)
1190                         bp->enabled |= BP_TRAP;
1191                 break;
1192         }
1193 }
1194
1195 /* Very cheap human name for vector lookup. */
1196 static
1197 const char *getvecname(unsigned long vec)
1198 {
1199         char *ret;
1200
1201         switch (vec) {
1202         case 0x100:     ret = "(System Reset)"; break;
1203         case 0x200:     ret = "(Machine Check)"; break;
1204         case 0x300:     ret = "(Data Access)"; break;
1205         case 0x380:     ret = "(Data SLB Access)"; break;
1206         case 0x400:     ret = "(Instruction Access)"; break;
1207         case 0x480:     ret = "(Instruction SLB Access)"; break;
1208         case 0x500:     ret = "(Hardware Interrupt)"; break;
1209         case 0x600:     ret = "(Alignment)"; break;
1210         case 0x700:     ret = "(Program Check)"; break;
1211         case 0x800:     ret = "(FPU Unavailable)"; break;
1212         case 0x900:     ret = "(Decrementer)"; break;
1213         case 0xc00:     ret = "(System Call)"; break;
1214         case 0xd00:     ret = "(Single Step)"; break;
1215         case 0xf00:     ret = "(Performance Monitor)"; break;
1216         case 0xf20:     ret = "(Altivec Unavailable)"; break;
1217         case 0x1300:    ret = "(Instruction Breakpoint)"; break;
1218         default: ret = "";
1219         }
1220         return ret;
1221 }
1222
1223 static void get_function_bounds(unsigned long pc, unsigned long *startp,
1224                                 unsigned long *endp)
1225 {
1226         unsigned long size, offset;
1227         const char *name;
1228
1229         *startp = *endp = 0;
1230         if (pc == 0)
1231                 return;
1232         if (setjmp(bus_error_jmp) == 0) {
1233                 catch_memory_errors = 1;
1234                 sync();
1235                 name = kallsyms_lookup(pc, &size, &offset, NULL, tmpstr);
1236                 if (name != NULL) {
1237                         *startp = pc - offset;
1238                         *endp = pc - offset + size;
1239                 }
1240                 sync();
1241         }
1242         catch_memory_errors = 0;
1243 }
1244
1245 static int xmon_depth_to_print = 64;
1246
1247 #ifdef CONFIG_PPC64
1248 #define LRSAVE_OFFSET           0x10
1249 #define REG_FRAME_MARKER        0x7265677368657265ul    /* "regshere" */
1250 #define MARKER_OFFSET           0x60
1251 #define REGS_OFFSET             0x70
1252 #else
1253 #define LRSAVE_OFFSET           4
1254 #define REG_FRAME_MARKER        0x72656773
1255 #define MARKER_OFFSET           8
1256 #define REGS_OFFSET             16
1257 #endif
1258
1259 static void xmon_show_stack(unsigned long sp, unsigned long lr,
1260                             unsigned long pc)
1261 {
1262         unsigned long ip;
1263         unsigned long newsp;
1264         unsigned long marker;
1265         int count = 0;
1266         struct pt_regs regs;
1267
1268         do {
1269                 if (sp < PAGE_OFFSET) {
1270                         if (sp != 0)
1271                                 printf("SP (%lx) is in userspace\n", sp);
1272                         break;
1273                 }
1274
1275                 if (!mread(sp + LRSAVE_OFFSET, &ip, sizeof(unsigned long))
1276                     || !mread(sp, &newsp, sizeof(unsigned long))) {
1277                         printf("Couldn't read stack frame at %lx\n", sp);
1278                         break;
1279                 }
1280
1281                 /*
1282                  * For the first stack frame, try to work out if
1283                  * LR and/or the saved LR value in the bottommost
1284                  * stack frame are valid.
1285                  */
1286                 if ((pc | lr) != 0) {
1287                         unsigned long fnstart, fnend;
1288                         unsigned long nextip;
1289                         int printip = 1;
1290
1291                         get_function_bounds(pc, &fnstart, &fnend);
1292                         nextip = 0;
1293                         if (newsp > sp)
1294                                 mread(newsp + LRSAVE_OFFSET, &nextip,
1295                                       sizeof(unsigned long));
1296                         if (lr == ip) {
1297                                 if (lr < PAGE_OFFSET
1298                                     || (fnstart <= lr && lr < fnend))
1299                                         printip = 0;
1300                         } else if (lr == nextip) {
1301                                 printip = 0;
1302                         } else if (lr >= PAGE_OFFSET
1303                                    && !(fnstart <= lr && lr < fnend)) {
1304                                 printf("[link register   ] ");
1305                                 xmon_print_symbol(lr, " ", "\n");
1306                         }
1307                         if (printip) {
1308                                 printf("["REG"] ", sp);
1309                                 xmon_print_symbol(ip, " ", " (unreliable)\n");
1310                         }
1311                         pc = lr = 0;
1312
1313                 } else {
1314                         printf("["REG"] ", sp);
1315                         xmon_print_symbol(ip, " ", "\n");
1316                 }
1317
1318                 /* Look for "regshere" marker to see if this is
1319                    an exception frame. */
1320                 if (mread(sp + MARKER_OFFSET, &marker, sizeof(unsigned long))
1321                     && marker == REG_FRAME_MARKER) {
1322                         if (mread(sp + REGS_OFFSET, &regs, sizeof(regs))
1323                             != sizeof(regs)) {
1324                                 printf("Couldn't read registers at %lx\n",
1325                                        sp + REGS_OFFSET);
1326                                 break;
1327                         }
1328                         printf("--- Exception: %lx %s at ", regs.trap,
1329                                getvecname(TRAP(&regs)));
1330                         pc = regs.nip;
1331                         lr = regs.link;
1332                         xmon_print_symbol(pc, " ", "\n");
1333                 }
1334
1335                 if (newsp == 0)
1336                         break;
1337
1338                 sp = newsp;
1339         } while (count++ < xmon_depth_to_print);
1340 }
1341
1342 static void backtrace(struct pt_regs *excp)
1343 {
1344         unsigned long sp;
1345
1346         if (scanhex(&sp))
1347                 xmon_show_stack(sp, 0, 0);
1348         else
1349                 xmon_show_stack(excp->gpr[1], excp->link, excp->nip);
1350         scannl();
1351 }
1352
1353 static void print_bug_trap(struct pt_regs *regs)
1354 {
1355         const struct bug_entry *bug;
1356         unsigned long addr;
1357
1358         if (regs->msr & MSR_PR)
1359                 return;         /* not in kernel */
1360         addr = regs->nip;       /* address of trap instruction */
1361         if (addr < PAGE_OFFSET)
1362                 return;
1363         bug = find_bug(regs->nip);
1364         if (bug == NULL)
1365                 return;
1366         if (is_warning_bug(bug))
1367                 return;
1368
1369 #ifdef CONFIG_DEBUG_BUGVERBOSE
1370         printf("kernel BUG at %s:%u!\n",
1371                bug->file, bug->line);
1372 #else
1373         printf("kernel BUG at %p!\n", (void *)bug->bug_addr);
1374 #endif
1375 }
1376
1377 void excprint(struct pt_regs *fp)
1378 {
1379         unsigned long trap;
1380
1381 #ifdef CONFIG_SMP
1382         printf("cpu 0x%x: ", smp_processor_id());
1383 #endif /* CONFIG_SMP */
1384
1385         trap = TRAP(fp);
1386         printf("Vector: %lx %s at [%lx]\n", fp->trap, getvecname(trap), fp);
1387         printf("    pc: ");
1388         xmon_print_symbol(fp->nip, ": ", "\n");
1389
1390         printf("    lr: ", fp->link);
1391         xmon_print_symbol(fp->link, ": ", "\n");
1392
1393         printf("    sp: %lx\n", fp->gpr[1]);
1394         printf("   msr: %lx\n", fp->msr);
1395
1396         if (trap == 0x300 || trap == 0x380 || trap == 0x600) {
1397                 printf("   dar: %lx\n", fp->dar);
1398                 if (trap != 0x380)
1399                         printf(" dsisr: %lx\n", fp->dsisr);
1400         }
1401
1402         printf("  current = 0x%lx\n", current);
1403 #ifdef CONFIG_PPC64
1404         printf("  paca    = 0x%lx\n", get_paca());
1405 #endif
1406         if (current) {
1407                 printf("    pid   = %ld, comm = %s\n",
1408                        current->pid, current->comm);
1409         }
1410
1411         if (trap == 0x700)
1412                 print_bug_trap(fp);
1413 }
1414
1415 void prregs(struct pt_regs *fp)
1416 {
1417         int n, trap;
1418         unsigned long base;
1419         struct pt_regs regs;
1420
1421         if (scanhex(&base)) {
1422                 if (setjmp(bus_error_jmp) == 0) {
1423                         catch_memory_errors = 1;
1424                         sync();
1425                         regs = *(struct pt_regs *)base;
1426                         sync();
1427                         __delay(200);
1428                 } else {
1429                         catch_memory_errors = 0;
1430                         printf("*** Error reading registers from "REG"\n",
1431                                base);
1432                         return;
1433                 }
1434                 catch_memory_errors = 0;
1435                 fp = &regs;
1436         }
1437
1438 #ifdef CONFIG_PPC64
1439         if (FULL_REGS(fp)) {
1440                 for (n = 0; n < 16; ++n)
1441                         printf("R%.2ld = "REG"   R%.2ld = "REG"\n",
1442                                n, fp->gpr[n], n+16, fp->gpr[n+16]);
1443         } else {
1444                 for (n = 0; n < 7; ++n)
1445                         printf("R%.2ld = "REG"   R%.2ld = "REG"\n",
1446                                n, fp->gpr[n], n+7, fp->gpr[n+7]);
1447         }
1448 #else
1449         for (n = 0; n < 32; ++n) {
1450                 printf("R%.2d = %.8x%s", n, fp->gpr[n],
1451                        (n & 3) == 3? "\n": "   ");
1452                 if (n == 12 && !FULL_REGS(fp)) {
1453                         printf("\n");
1454                         break;
1455                 }
1456         }
1457 #endif
1458         printf("pc  = ");
1459         xmon_print_symbol(fp->nip, " ", "\n");
1460         printf("lr  = ");
1461         xmon_print_symbol(fp->link, " ", "\n");
1462         printf("msr = "REG"   cr  = %.8lx\n", fp->msr, fp->ccr);
1463         printf("ctr = "REG"   xer = "REG"   trap = %4lx\n",
1464                fp->ctr, fp->xer, fp->trap);
1465         trap = TRAP(fp);
1466         if (trap == 0x300 || trap == 0x380 || trap == 0x600)
1467                 printf("dar = "REG"   dsisr = %.8lx\n", fp->dar, fp->dsisr);
1468 }
1469
1470 void cacheflush(void)
1471 {
1472         int cmd;
1473         unsigned long nflush;
1474
1475         cmd = inchar();
1476         if (cmd != 'i')
1477                 termch = cmd;
1478         scanhex((void *)&adrs);
1479         if (termch != '\n')
1480                 termch = 0;
1481         nflush = 1;
1482         scanhex(&nflush);
1483         nflush = (nflush + L1_CACHE_BYTES - 1) / L1_CACHE_BYTES;
1484         if (setjmp(bus_error_jmp) == 0) {
1485                 catch_memory_errors = 1;
1486                 sync();
1487
1488                 if (cmd != 'i') {
1489                         for (; nflush > 0; --nflush, adrs += L1_CACHE_BYTES)
1490                                 cflush((void *) adrs);
1491                 } else {
1492                         for (; nflush > 0; --nflush, adrs += L1_CACHE_BYTES)
1493                                 cinval((void *) adrs);
1494                 }
1495                 sync();
1496                 /* wait a little while to see if we get a machine check */
1497                 __delay(200);
1498         }
1499         catch_memory_errors = 0;
1500 }
1501
1502 unsigned long
1503 read_spr(int n)
1504 {
1505         unsigned int instrs[2];
1506         unsigned long (*code)(void);
1507         unsigned long ret = -1UL;
1508 #ifdef CONFIG_PPC64
1509         unsigned long opd[3];
1510
1511         opd[0] = (unsigned long)instrs;
1512         opd[1] = 0;
1513         opd[2] = 0;
1514         code = (unsigned long (*)(void)) opd;
1515 #else
1516         code = (unsigned long (*)(void)) instrs;
1517 #endif
1518
1519         /* mfspr r3,n; blr */
1520         instrs[0] = 0x7c6002a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
1521         instrs[1] = 0x4e800020;
1522         store_inst(instrs);
1523         store_inst(instrs+1);
1524
1525         if (setjmp(bus_error_jmp) == 0) {
1526                 catch_memory_errors = 1;
1527                 sync();
1528
1529                 ret = code();
1530
1531                 sync();
1532                 /* wait a little while to see if we get a machine check */
1533                 __delay(200);
1534                 n = size;
1535         }
1536
1537         return ret;
1538 }
1539
1540 void
1541 write_spr(int n, unsigned long val)
1542 {
1543         unsigned int instrs[2];
1544         unsigned long (*code)(unsigned long);
1545 #ifdef CONFIG_PPC64
1546         unsigned long opd[3];
1547
1548         opd[0] = (unsigned long)instrs;
1549         opd[1] = 0;
1550         opd[2] = 0;
1551         code = (unsigned long (*)(unsigned long)) opd;
1552 #else
1553         code = (unsigned long (*)(unsigned long)) instrs;
1554 #endif
1555
1556         instrs[0] = 0x7c6003a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
1557         instrs[1] = 0x4e800020;
1558         store_inst(instrs);
1559         store_inst(instrs+1);
1560
1561         if (setjmp(bus_error_jmp) == 0) {
1562                 catch_memory_errors = 1;
1563                 sync();
1564
1565                 code(val);
1566
1567                 sync();
1568                 /* wait a little while to see if we get a machine check */
1569                 __delay(200);
1570                 n = size;
1571         }
1572 }
1573
1574 static unsigned long regno;
1575 extern char exc_prolog;
1576 extern char dec_exc;
1577
1578 void super_regs(void)
1579 {
1580         int cmd;
1581         unsigned long val;
1582
1583         cmd = skipbl();
1584         if (cmd == '\n') {
1585                 unsigned long sp, toc;
1586                 asm("mr %0,1" : "=r" (sp) :);
1587                 asm("mr %0,2" : "=r" (toc) :);
1588
1589                 printf("msr  = "REG"  sprg0= "REG"\n",
1590                        mfmsr(), mfspr(SPRN_SPRG0));
1591                 printf("pvr  = "REG"  sprg1= "REG"\n",
1592                        mfspr(SPRN_PVR), mfspr(SPRN_SPRG1)); 
1593                 printf("dec  = "REG"  sprg2= "REG"\n",
1594                        mfspr(SPRN_DEC), mfspr(SPRN_SPRG2));
1595                 printf("sp   = "REG"  sprg3= "REG"\n", sp, mfspr(SPRN_SPRG3));
1596                 printf("toc  = "REG"  dar  = "REG"\n", toc, mfspr(SPRN_DAR));
1597 #ifdef CONFIG_PPC_ISERIES
1598                 if (firmware_has_feature(FW_FEATURE_ISERIES)) {
1599                         struct paca_struct *ptrPaca;
1600                         struct lppaca *ptrLpPaca;
1601                         struct ItLpRegSave *ptrLpRegSave;
1602
1603                         /* Dump out relevant Paca data areas. */
1604                         printf("Paca: \n");
1605                         ptrPaca = get_paca();
1606
1607                         printf("  Local Processor Control Area (LpPaca): \n");
1608                         ptrLpPaca = ptrPaca->lppaca_ptr;
1609                         printf("    Saved Srr0=%.16lx  Saved Srr1=%.16lx \n",
1610                                ptrLpPaca->saved_srr0, ptrLpPaca->saved_srr1);
1611                         printf("    Saved Gpr3=%.16lx  Saved Gpr4=%.16lx \n",
1612                                ptrLpPaca->saved_gpr3, ptrLpPaca->saved_gpr4);
1613                         printf("    Saved Gpr5=%.16lx \n", ptrLpPaca->saved_gpr5);
1614
1615                         printf("  Local Processor Register Save Area (LpRegSave): \n");
1616                         ptrLpRegSave = ptrPaca->reg_save_ptr;
1617                         printf("    Saved Sprg0=%.16lx  Saved Sprg1=%.16lx \n",
1618                                ptrLpRegSave->xSPRG0, ptrLpRegSave->xSPRG0);
1619                         printf("    Saved Sprg2=%.16lx  Saved Sprg3=%.16lx \n",
1620                                ptrLpRegSave->xSPRG2, ptrLpRegSave->xSPRG3);
1621                         printf("    Saved Msr  =%.16lx  Saved Nia  =%.16lx \n",
1622                                ptrLpRegSave->xMSR, ptrLpRegSave->xNIA);
1623                 }
1624 #endif
1625
1626                 return;
1627         }
1628
1629         scanhex(&regno);
1630         switch (cmd) {
1631         case 'w':
1632                 val = read_spr(regno);
1633                 scanhex(&val);
1634                 write_spr(regno, val);
1635                 /* fall through */
1636         case 'r':
1637                 printf("spr %lx = %lx\n", regno, read_spr(regno));
1638                 break;
1639         }
1640         scannl();
1641 }
1642
1643 /*
1644  * Stuff for reading and writing memory safely
1645  */
1646 int
1647 mread(unsigned long adrs, void *buf, int size)
1648 {
1649         volatile int n;
1650         char *p, *q;
1651
1652         n = 0;
1653         if (setjmp(bus_error_jmp) == 0) {
1654                 catch_memory_errors = 1;
1655                 sync();
1656                 p = (char *)adrs;
1657                 q = (char *)buf;
1658                 switch (size) {
1659                 case 2:
1660                         *(u16 *)q = *(u16 *)p;
1661                         break;
1662                 case 4:
1663                         *(u32 *)q = *(u32 *)p;
1664                         break;
1665                 case 8:
1666                         *(u64 *)q = *(u64 *)p;
1667                         break;
1668                 default:
1669                         for( ; n < size; ++n) {
1670                                 *q++ = *p++;
1671                                 sync();
1672                         }
1673                 }
1674                 sync();
1675                 /* wait a little while to see if we get a machine check */
1676                 __delay(200);
1677                 n = size;
1678         }
1679         catch_memory_errors = 0;
1680         return n;
1681 }
1682
1683 int
1684 mwrite(unsigned long adrs, void *buf, int size)
1685 {
1686         volatile int n;
1687         char *p, *q;
1688
1689         n = 0;
1690         if (setjmp(bus_error_jmp) == 0) {
1691                 catch_memory_errors = 1;
1692                 sync();
1693                 p = (char *) adrs;
1694                 q = (char *) buf;
1695                 switch (size) {
1696                 case 2:
1697                         *(u16 *)p = *(u16 *)q;
1698                         break;
1699                 case 4:
1700                         *(u32 *)p = *(u32 *)q;
1701                         break;
1702                 case 8:
1703                         *(u64 *)p = *(u64 *)q;
1704                         break;
1705                 default:
1706                         for ( ; n < size; ++n) {
1707                                 *p++ = *q++;
1708                                 sync();
1709                         }
1710                 }
1711                 sync();
1712                 /* wait a little while to see if we get a machine check */
1713                 __delay(200);
1714                 n = size;
1715         } else {
1716                 printf("*** Error writing address %x\n", adrs + n);
1717         }
1718         catch_memory_errors = 0;
1719         return n;
1720 }
1721
1722 static int fault_type;
1723 static int fault_except;
1724 static char *fault_chars[] = { "--", "**", "##" };
1725
1726 static int handle_fault(struct pt_regs *regs)
1727 {
1728         fault_except = TRAP(regs);
1729         switch (TRAP(regs)) {
1730         case 0x200:
1731                 fault_type = 0;
1732                 break;
1733         case 0x300:
1734         case 0x380:
1735                 fault_type = 1;
1736                 break;
1737         default:
1738                 fault_type = 2;
1739         }
1740
1741         longjmp(bus_error_jmp, 1);
1742
1743         return 0;
1744 }
1745
1746 #define SWAP(a, b, t)   ((t) = (a), (a) = (b), (b) = (t))
1747
1748 void
1749 byterev(unsigned char *val, int size)
1750 {
1751         int t;
1752         
1753         switch (size) {
1754         case 2:
1755                 SWAP(val[0], val[1], t);
1756                 break;
1757         case 4:
1758                 SWAP(val[0], val[3], t);
1759                 SWAP(val[1], val[2], t);
1760                 break;
1761         case 8: /* is there really any use for this? */
1762                 SWAP(val[0], val[7], t);
1763                 SWAP(val[1], val[6], t);
1764                 SWAP(val[2], val[5], t);
1765                 SWAP(val[3], val[4], t);
1766                 break;
1767         }
1768 }
1769
1770 static int brev;
1771 static int mnoread;
1772
1773 static char *memex_help_string = 
1774     "Memory examine command usage:\n"
1775     "m [addr] [flags] examine/change memory\n"
1776     "  addr is optional.  will start where left off.\n"
1777     "  flags may include chars from this set:\n"
1778     "    b   modify by bytes (default)\n"
1779     "    w   modify by words (2 byte)\n"
1780     "    l   modify by longs (4 byte)\n"
1781     "    d   modify by doubleword (8 byte)\n"
1782     "    r   toggle reverse byte order mode\n"
1783     "    n   do not read memory (for i/o spaces)\n"
1784     "    .   ok to read (default)\n"
1785     "NOTE: flags are saved as defaults\n"
1786     "";
1787
1788 static char *memex_subcmd_help_string = 
1789     "Memory examine subcommands:\n"
1790     "  hexval   write this val to current location\n"
1791     "  'string' write chars from string to this location\n"
1792     "  '        increment address\n"
1793     "  ^        decrement address\n"
1794     "  /        increment addr by 0x10.  //=0x100, ///=0x1000, etc\n"
1795     "  \\        decrement addr by 0x10.  \\\\=0x100, \\\\\\=0x1000, etc\n"
1796     "  `        clear no-read flag\n"
1797     "  ;        stay at this addr\n"
1798     "  v        change to byte mode\n"
1799     "  w        change to word (2 byte) mode\n"
1800     "  l        change to long (4 byte) mode\n"
1801     "  u        change to doubleword (8 byte) mode\n"
1802     "  m addr   change current addr\n"
1803     "  n        toggle no-read flag\n"
1804     "  r        toggle byte reverse flag\n"
1805     "  < count  back up count bytes\n"
1806     "  > count  skip forward count bytes\n"
1807     "  x        exit this mode\n"
1808     "";
1809
1810 void
1811 memex(void)
1812 {
1813         int cmd, inc, i, nslash;
1814         unsigned long n;
1815         unsigned char val[16];
1816
1817         scanhex((void *)&adrs);
1818         cmd = skipbl();
1819         if (cmd == '?') {
1820                 printf(memex_help_string);
1821                 return;
1822         } else {
1823                 termch = cmd;
1824         }
1825         last_cmd = "m\n";
1826         while ((cmd = skipbl()) != '\n') {
1827                 switch( cmd ){
1828                 case 'b':       size = 1;       break;
1829                 case 'w':       size = 2;       break;
1830                 case 'l':       size = 4;       break;
1831                 case 'd':       size = 8;       break;
1832                 case 'r':       brev = !brev;   break;
1833                 case 'n':       mnoread = 1;    break;
1834                 case '.':       mnoread = 0;    break;
1835                 }
1836         }
1837         if( size <= 0 )
1838                 size = 1;
1839         else if( size > 8 )
1840                 size = 8;
1841         for(;;){
1842                 if (!mnoread)
1843                         n = mread(adrs, val, size);
1844                 printf(REG"%c", adrs, brev? 'r': ' ');
1845                 if (!mnoread) {
1846                         if (brev)
1847                                 byterev(val, size);
1848                         putchar(' ');
1849                         for (i = 0; i < n; ++i)
1850                                 printf("%.2x", val[i]);
1851                         for (; i < size; ++i)
1852                                 printf("%s", fault_chars[fault_type]);
1853                 }
1854                 putchar(' ');
1855                 inc = size;
1856                 nslash = 0;
1857                 for(;;){
1858                         if( scanhex(&n) ){
1859                                 for (i = 0; i < size; ++i)
1860                                         val[i] = n >> (i * 8);
1861                                 if (!brev)
1862                                         byterev(val, size);
1863                                 mwrite(adrs, val, size);
1864                                 inc = size;
1865                         }
1866                         cmd = skipbl();
1867                         if (cmd == '\n')
1868                                 break;
1869                         inc = 0;
1870                         switch (cmd) {
1871                         case '\'':
1872                                 for(;;){
1873                                         n = inchar();
1874                                         if( n == '\\' )
1875                                                 n = bsesc();
1876                                         else if( n == '\'' )
1877                                                 break;
1878                                         for (i = 0; i < size; ++i)
1879                                                 val[i] = n >> (i * 8);
1880                                         if (!brev)
1881                                                 byterev(val, size);
1882                                         mwrite(adrs, val, size);
1883                                         adrs += size;
1884                                 }
1885                                 adrs -= size;
1886                                 inc = size;
1887                                 break;
1888                         case ',':
1889                                 adrs += size;
1890                                 break;
1891                         case '.':
1892                                 mnoread = 0;
1893                                 break;
1894                         case ';':
1895                                 break;
1896                         case 'x':
1897                         case EOF:
1898                                 scannl();
1899                                 return;
1900                         case 'b':
1901                         case 'v':
1902                                 size = 1;
1903                                 break;
1904                         case 'w':
1905                                 size = 2;
1906                                 break;
1907                         case 'l':
1908                                 size = 4;
1909                                 break;
1910                         case 'u':
1911                                 size = 8;
1912                                 break;
1913                         case '^':
1914                                 adrs -= size;
1915                                 break;
1916                                 break;
1917                         case '/':
1918                                 if (nslash > 0)
1919                                         adrs -= 1 << nslash;
1920                                 else
1921                                         nslash = 0;
1922                                 nslash += 4;
1923                                 adrs += 1 << nslash;
1924                                 break;
1925                         case '\\':
1926                                 if (nslash < 0)
1927                                         adrs += 1 << -nslash;
1928                                 else
1929                                         nslash = 0;
1930                                 nslash -= 4;
1931                                 adrs -= 1 << -nslash;
1932                                 break;
1933                         case 'm':
1934                                 scanhex((void *)&adrs);
1935                                 break;
1936                         case 'n':
1937                                 mnoread = 1;
1938                                 break;
1939                         case 'r':
1940                                 brev = !brev;
1941                                 break;
1942                         case '<':
1943                                 n = size;
1944                                 scanhex(&n);
1945                                 adrs -= n;
1946                                 break;
1947                         case '>':
1948                                 n = size;
1949                                 scanhex(&n);
1950                                 adrs += n;
1951                                 break;
1952                         case '?':
1953                                 printf(memex_subcmd_help_string);
1954                                 break;
1955                         }
1956                 }
1957                 adrs += inc;
1958         }
1959 }
1960
1961 int
1962 bsesc(void)
1963 {
1964         int c;
1965
1966         c = inchar();
1967         switch( c ){
1968         case 'n':       c = '\n';       break;
1969         case 'r':       c = '\r';       break;
1970         case 'b':       c = '\b';       break;
1971         case 't':       c = '\t';       break;
1972         }
1973         return c;
1974 }
1975
1976 static void xmon_rawdump (unsigned long adrs, long ndump)
1977 {
1978         long n, m, r, nr;
1979         unsigned char temp[16];
1980
1981         for (n = ndump; n > 0;) {
1982                 r = n < 16? n: 16;
1983                 nr = mread(adrs, temp, r);
1984                 adrs += nr;
1985                 for (m = 0; m < r; ++m) {
1986                         if (m < nr)
1987                                 printf("%.2x", temp[m]);
1988                         else
1989                                 printf("%s", fault_chars[fault_type]);
1990                 }
1991                 n -= r;
1992                 if (nr < r)
1993                         break;
1994         }
1995         printf("\n");
1996 }
1997
1998 #define isxdigit(c)     (('0' <= (c) && (c) <= '9') \
1999                          || ('a' <= (c) && (c) <= 'f') \
2000                          || ('A' <= (c) && (c) <= 'F'))
2001 void
2002 dump(void)
2003 {
2004         int c;
2005
2006         c = inchar();
2007         if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')
2008                 termch = c;
2009         scanhex((void *)&adrs);
2010         if (termch != '\n')
2011                 termch = 0;
2012         if (c == 'i') {
2013                 scanhex(&nidump);
2014                 if (nidump == 0)
2015                         nidump = 16;
2016                 else if (nidump > MAX_DUMP)
2017                         nidump = MAX_DUMP;
2018                 adrs += ppc_inst_dump(adrs, nidump, 1);
2019                 last_cmd = "di\n";
2020         } else if (c == 'r') {
2021                 scanhex(&ndump);
2022                 if (ndump == 0)
2023                         ndump = 64;
2024                 xmon_rawdump(adrs, ndump);
2025                 adrs += ndump;
2026                 last_cmd = "dr\n";
2027         } else {
2028                 scanhex(&ndump);
2029                 if (ndump == 0)
2030                         ndump = 64;
2031                 else if (ndump > MAX_DUMP)
2032                         ndump = MAX_DUMP;
2033                 prdump(adrs, ndump);
2034                 adrs += ndump;
2035                 last_cmd = "d\n";
2036         }
2037 }
2038
2039 void
2040 prdump(unsigned long adrs, long ndump)
2041 {
2042         long n, m, c, r, nr;
2043         unsigned char temp[16];
2044
2045         for (n = ndump; n > 0;) {
2046                 printf(REG, adrs);
2047                 putchar(' ');
2048                 r = n < 16? n: 16;
2049                 nr = mread(adrs, temp, r);
2050                 adrs += nr;
2051                 for (m = 0; m < r; ++m) {
2052                         if ((m & (sizeof(long) - 1)) == 0 && m > 0)
2053                                 putchar(' ');
2054                         if (m < nr)
2055                                 printf("%.2x", temp[m]);
2056                         else
2057                                 printf("%s", fault_chars[fault_type]);
2058                 }
2059                 for (; m < 16; ++m) {
2060                         if ((m & (sizeof(long) - 1)) == 0)
2061                                 putchar(' ');
2062                         printf("  ");
2063                 }
2064                 printf("  |");
2065                 for (m = 0; m < r; ++m) {
2066                         if (m < nr) {
2067                                 c = temp[m];
2068                                 putchar(' ' <= c && c <= '~'? c: '.');
2069                         } else
2070                                 putchar(' ');
2071                 }
2072                 n -= r;
2073                 for (; m < 16; ++m)
2074                         putchar(' ');
2075                 printf("|\n");
2076                 if (nr < r)
2077                         break;
2078         }
2079 }
2080
2081 typedef int (*instruction_dump_func)(unsigned long inst, unsigned long addr);
2082
2083 int
2084 generic_inst_dump(unsigned long adr, long count, int praddr,
2085                         instruction_dump_func dump_func)
2086 {
2087         int nr, dotted;
2088         unsigned long first_adr;
2089         unsigned long inst, last_inst = 0;
2090         unsigned char val[4];
2091
2092         dotted = 0;
2093         for (first_adr = adr; count > 0; --count, adr += 4) {
2094                 nr = mread(adr, val, 4);
2095                 if (nr == 0) {
2096                         if (praddr) {
2097                                 const char *x = fault_chars[fault_type];
2098                                 printf(REG"  %s%s%s%s\n", adr, x, x, x, x);
2099                         }
2100                         break;
2101                 }
2102                 inst = GETWORD(val);
2103                 if (adr > first_adr && inst == last_inst) {
2104                         if (!dotted) {
2105                                 printf(" ...\n");
2106                                 dotted = 1;
2107                         }
2108                         continue;
2109                 }
2110                 dotted = 0;
2111                 last_inst = inst;
2112                 if (praddr)
2113                         printf(REG"  %.8x", adr, inst);
2114                 printf("\t");
2115                 dump_func(inst, adr);
2116                 printf("\n");
2117         }
2118         return adr - first_adr;
2119 }
2120
2121 int
2122 ppc_inst_dump(unsigned long adr, long count, int praddr)
2123 {
2124         return generic_inst_dump(adr, count, praddr, print_insn_powerpc);
2125 }
2126
2127 void
2128 print_address(unsigned long addr)
2129 {
2130         xmon_print_symbol(addr, "\t# ", "");
2131 }
2132
2133
2134 /*
2135  * Memory operations - move, set, print differences
2136  */
2137 static unsigned long mdest;             /* destination address */
2138 static unsigned long msrc;              /* source address */
2139 static unsigned long mval;              /* byte value to set memory to */
2140 static unsigned long mcount;            /* # bytes to affect */
2141 static unsigned long mdiffs;            /* max # differences to print */
2142
2143 void
2144 memops(int cmd)
2145 {
2146         scanhex((void *)&mdest);
2147         if( termch != '\n' )
2148                 termch = 0;
2149         scanhex((void *)(cmd == 's'? &mval: &msrc));
2150         if( termch != '\n' )
2151                 termch = 0;
2152         scanhex((void *)&mcount);
2153         switch( cmd ){
2154         case 'm':
2155                 memmove((void *)mdest, (void *)msrc, mcount);
2156                 break;
2157         case 's':
2158                 memset((void *)mdest, mval, mcount);
2159                 break;
2160         case 'd':
2161                 if( termch != '\n' )
2162                         termch = 0;
2163                 scanhex((void *)&mdiffs);
2164                 memdiffs((unsigned char *)mdest, (unsigned char *)msrc, mcount, mdiffs);
2165                 break;
2166         }
2167 }
2168
2169 void
2170 memdiffs(unsigned char *p1, unsigned char *p2, unsigned nb, unsigned maxpr)
2171 {
2172         unsigned n, prt;
2173
2174         prt = 0;
2175         for( n = nb; n > 0; --n )
2176                 if( *p1++ != *p2++ )
2177                         if( ++prt <= maxpr )
2178                                 printf("%.16x %.2x # %.16x %.2x\n", p1 - 1,
2179                                         p1[-1], p2 - 1, p2[-1]);
2180         if( prt > maxpr )
2181                 printf("Total of %d differences\n", prt);
2182 }
2183
2184 static unsigned mend;
2185 static unsigned mask;
2186
2187 void
2188 memlocate(void)
2189 {
2190         unsigned a, n;
2191         unsigned char val[4];
2192
2193         last_cmd = "ml";
2194         scanhex((void *)&mdest);
2195         if (termch != '\n') {
2196                 termch = 0;
2197                 scanhex((void *)&mend);
2198                 if (termch != '\n') {
2199                         termch = 0;
2200                         scanhex((void *)&mval);
2201                         mask = ~0;
2202                         if (termch != '\n') termch = 0;
2203                         scanhex((void *)&mask);
2204                 }
2205         }
2206         n = 0;
2207         for (a = mdest; a < mend; a += 4) {
2208                 if (mread(a, val, 4) == 4
2209                         && ((GETWORD(val) ^ mval) & mask) == 0) {
2210                         printf("%.16x:  %.16x\n", a, GETWORD(val));
2211                         if (++n >= 10)
2212                                 break;
2213                 }
2214         }
2215 }
2216
2217 static unsigned long mskip = 0x1000;
2218 static unsigned long mlim = 0xffffffff;
2219
2220 void
2221 memzcan(void)
2222 {
2223         unsigned char v;
2224         unsigned a;
2225         int ok, ook;
2226
2227         scanhex(&mdest);
2228         if (termch != '\n') termch = 0;
2229         scanhex(&mskip);
2230         if (termch != '\n') termch = 0;
2231         scanhex(&mlim);
2232         ook = 0;
2233         for (a = mdest; a < mlim; a += mskip) {
2234                 ok = mread(a, &v, 1);
2235                 if (ok && !ook) {
2236                         printf("%.8x .. ", a);
2237                 } else if (!ok && ook)
2238                         printf("%.8x\n", a - mskip);
2239                 ook = ok;
2240                 if (a + mskip < a)
2241                         break;
2242         }
2243         if (ook)
2244                 printf("%.8x\n", a - mskip);
2245 }
2246
2247 void proccall(void)
2248 {
2249         unsigned long args[8];
2250         unsigned long ret;
2251         int i;
2252         typedef unsigned long (*callfunc_t)(unsigned long, unsigned long,
2253                         unsigned long, unsigned long, unsigned long,
2254                         unsigned long, unsigned long, unsigned long);
2255         callfunc_t func;
2256
2257         if (!scanhex(&adrs))
2258                 return;
2259         if (termch != '\n')
2260                 termch = 0;
2261         for (i = 0; i < 8; ++i)
2262                 args[i] = 0;
2263         for (i = 0; i < 8; ++i) {
2264                 if (!scanhex(&args[i]) || termch == '\n')
2265                         break;
2266                 termch = 0;
2267         }
2268         func = (callfunc_t) adrs;
2269         ret = 0;
2270         if (setjmp(bus_error_jmp) == 0) {
2271                 catch_memory_errors = 1;
2272                 sync();
2273                 ret = func(args[0], args[1], args[2], args[3],
2274                            args[4], args[5], args[6], args[7]);
2275                 sync();
2276                 printf("return value is %x\n", ret);
2277         } else {
2278                 printf("*** %x exception occurred\n", fault_except);
2279         }
2280         catch_memory_errors = 0;
2281 }
2282
2283 /* Input scanning routines */
2284 int
2285 skipbl(void)
2286 {
2287         int c;
2288
2289         if( termch != 0 ){
2290                 c = termch;
2291                 termch = 0;
2292         } else
2293                 c = inchar();
2294         while( c == ' ' || c == '\t' )
2295                 c = inchar();
2296         return c;
2297 }
2298
2299 #define N_PTREGS        44
2300 static char *regnames[N_PTREGS] = {
2301         "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
2302         "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
2303         "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
2304         "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
2305         "pc", "msr", "or3", "ctr", "lr", "xer", "ccr",
2306 #ifdef CONFIG_PPC64
2307         "softe",
2308 #else
2309         "mq",
2310 #endif
2311         "trap", "dar", "dsisr", "res"
2312 };
2313
2314 int
2315 scanhex(unsigned long *vp)
2316 {
2317         int c, d;
2318         unsigned long v;
2319
2320         c = skipbl();
2321         if (c == '%') {
2322                 /* parse register name */
2323                 char regname[8];
2324                 int i;
2325
2326                 for (i = 0; i < sizeof(regname) - 1; ++i) {
2327                         c = inchar();
2328                         if (!isalnum(c)) {
2329                                 termch = c;
2330                                 break;
2331                         }
2332                         regname[i] = c;
2333                 }
2334                 regname[i] = 0;
2335                 for (i = 0; i < N_PTREGS; ++i) {
2336                         if (strcmp(regnames[i], regname) == 0) {
2337                                 if (xmon_regs == NULL) {
2338                                         printf("regs not available\n");
2339                                         return 0;
2340                                 }
2341                                 *vp = ((unsigned long *)xmon_regs)[i];
2342                                 return 1;
2343                         }
2344                 }
2345                 printf("invalid register name '%%%s'\n", regname);
2346                 return 0;
2347         }
2348
2349         /* skip leading "0x" if any */
2350
2351         if (c == '0') {
2352                 c = inchar();
2353                 if (c == 'x') {
2354                         c = inchar();
2355                 } else {
2356                         d = hexdigit(c);
2357                         if (d == EOF) {
2358                                 termch = c;
2359                                 *vp = 0;
2360                                 return 1;
2361                         }
2362                 }
2363         } else if (c == '$') {
2364                 int i;
2365                 for (i=0; i<63; i++) {
2366                         c = inchar();
2367                         if (isspace(c)) {
2368                                 termch = c;
2369                                 break;
2370                         }
2371                         tmpstr[i] = c;
2372                 }
2373                 tmpstr[i++] = 0;
2374                 *vp = 0;
2375                 if (setjmp(bus_error_jmp) == 0) {
2376                         catch_memory_errors = 1;
2377                         sync();
2378                         *vp = kallsyms_lookup_name(tmpstr);
2379                         sync();
2380                 }
2381                 catch_memory_errors = 0;
2382                 if (!(*vp)) {
2383                         printf("unknown symbol '%s'\n", tmpstr);
2384                         return 0;
2385                 }
2386                 return 1;
2387         }
2388
2389         d = hexdigit(c);
2390         if (d == EOF) {
2391                 termch = c;
2392                 return 0;
2393         }
2394         v = 0;
2395         do {
2396                 v = (v << 4) + d;
2397                 c = inchar();
2398                 d = hexdigit(c);
2399         } while (d != EOF);
2400         termch = c;
2401         *vp = v;
2402         return 1;
2403 }
2404
2405 void
2406 scannl(void)
2407 {
2408         int c;
2409
2410         c = termch;
2411         termch = 0;
2412         while( c != '\n' )
2413                 c = inchar();
2414 }
2415
2416 int hexdigit(int c)
2417 {
2418         if( '0' <= c && c <= '9' )
2419                 return c - '0';
2420         if( 'A' <= c && c <= 'F' )
2421                 return c - ('A' - 10);
2422         if( 'a' <= c && c <= 'f' )
2423                 return c - ('a' - 10);
2424         return EOF;
2425 }
2426
2427 void
2428 getstring(char *s, int size)
2429 {
2430         int c;
2431
2432         c = skipbl();
2433         do {
2434                 if( size > 1 ){
2435                         *s++ = c;
2436                         --size;
2437                 }
2438                 c = inchar();
2439         } while( c != ' ' && c != '\t' && c != '\n' );
2440         termch = c;
2441         *s = 0;
2442 }
2443
2444 static char line[256];
2445 static char *lineptr;
2446
2447 void
2448 flush_input(void)
2449 {
2450         lineptr = NULL;
2451 }
2452
2453 int
2454 inchar(void)
2455 {
2456         if (lineptr == NULL || *lineptr == 0) {
2457                 if (xmon_gets(line, sizeof(line)) == NULL) {
2458                         lineptr = NULL;
2459                         return EOF;
2460                 }
2461                 lineptr = line;
2462         }
2463         return *lineptr++;
2464 }
2465
2466 void
2467 take_input(char *str)
2468 {
2469         lineptr = str;
2470 }
2471
2472
2473 static void
2474 symbol_lookup(void)
2475 {
2476         int type = inchar();
2477         unsigned long addr;
2478         static char tmp[64];
2479
2480         switch (type) {
2481         case 'a':
2482                 if (scanhex(&addr))
2483                         xmon_print_symbol(addr, ": ", "\n");
2484                 termch = 0;
2485                 break;
2486         case 's':
2487                 getstring(tmp, 64);
2488                 if (setjmp(bus_error_jmp) == 0) {
2489                         catch_memory_errors = 1;
2490                         sync();
2491                         addr = kallsyms_lookup_name(tmp);
2492                         if (addr)
2493                                 printf("%s: %lx\n", tmp, addr);
2494                         else
2495                                 printf("Symbol '%s' not found.\n", tmp);
2496                         sync();
2497                 }
2498                 catch_memory_errors = 0;
2499                 termch = 0;
2500                 break;
2501         }
2502 }
2503
2504
2505 /* Print an address in numeric and symbolic form (if possible) */
2506 static void xmon_print_symbol(unsigned long address, const char *mid,
2507                               const char *after)
2508 {
2509         char *modname;
2510         const char *name = NULL;
2511         unsigned long offset, size;
2512
2513         printf(REG, address);
2514         if (setjmp(bus_error_jmp) == 0) {
2515                 catch_memory_errors = 1;
2516                 sync();
2517                 name = kallsyms_lookup(address, &size, &offset, &modname,
2518                                        tmpstr);
2519                 sync();
2520                 /* wait a little while to see if we get a machine check */
2521                 __delay(200);
2522         }
2523
2524         catch_memory_errors = 0;
2525
2526         if (name) {
2527                 printf("%s%s+%#lx/%#lx", mid, name, offset, size);
2528                 if (modname)
2529                         printf(" [%s]", modname);
2530         }
2531         printf("%s", after);
2532 }
2533
2534 #ifdef CONFIG_PPC64
2535 static void dump_slb(void)
2536 {
2537         int i;
2538         unsigned long esid,vsid,valid;
2539         unsigned long llp;
2540
2541         printf("SLB contents of cpu %x\n", smp_processor_id());
2542
2543         for (i = 0; i < mmu_slb_size; i++) {
2544                 asm volatile("slbmfee  %0,%1" : "=r" (esid) : "r" (i));
2545                 asm volatile("slbmfev  %0,%1" : "=r" (vsid) : "r" (i));
2546                 valid = (esid & SLB_ESID_V);
2547                 if (valid | esid | vsid) {
2548                         printf("%02d %016lx %016lx", i, esid, vsid);
2549                         if (valid) {
2550                                 llp = vsid & SLB_VSID_LLP;
2551                                 if (vsid & SLB_VSID_B_1T) {
2552                                         printf("  1T  ESID=%9lx  VSID=%13lx LLP:%3lx \n",
2553                                                 GET_ESID_1T(esid),
2554                                                 (vsid & ~SLB_VSID_B) >> SLB_VSID_SHIFT_1T,
2555                                                 llp);
2556                                 } else {
2557                                         printf(" 256M ESID=%9lx  VSID=%13lx LLP:%3lx \n",
2558                                                 GET_ESID(esid),
2559                                                 (vsid & ~SLB_VSID_B) >> SLB_VSID_SHIFT,
2560                                                 llp);
2561                                 }
2562                         } else
2563                                 printf("\n");
2564                 }
2565         }
2566 }
2567
2568 static void dump_stab(void)
2569 {
2570         int i;
2571         unsigned long *tmp = (unsigned long *)get_paca()->stab_addr;
2572
2573         printf("Segment table contents of cpu %x\n", smp_processor_id());
2574
2575         for (i = 0; i < PAGE_SIZE/16; i++) {
2576                 unsigned long a, b;
2577
2578                 a = *tmp++;
2579                 b = *tmp++;
2580
2581                 if (a || b) {
2582                         printf("%03d %016lx ", i, a);
2583                         printf("%016lx\n", b);
2584                 }
2585         }
2586 }
2587
2588 void dump_segments(void)
2589 {
2590         if (cpu_has_feature(CPU_FTR_SLB))
2591                 dump_slb();
2592         else
2593                 dump_stab();
2594 }
2595 #endif
2596
2597 #ifdef CONFIG_PPC_STD_MMU_32
2598 void dump_segments(void)
2599 {
2600         int i;
2601
2602         printf("sr0-15 =");
2603         for (i = 0; i < 16; ++i)
2604                 printf(" %x", mfsrin(i));
2605         printf("\n");
2606 }
2607 #endif
2608
2609 #ifdef CONFIG_44x
2610 static void dump_tlb_44x(void)
2611 {
2612         int i;
2613
2614         for (i = 0; i < PPC44x_TLB_SIZE; i++) {
2615                 unsigned long w0,w1,w2;
2616                 asm volatile("tlbre  %0,%1,0" : "=r" (w0) : "r" (i));
2617                 asm volatile("tlbre  %0,%1,1" : "=r" (w1) : "r" (i));
2618                 asm volatile("tlbre  %0,%1,2" : "=r" (w2) : "r" (i));
2619                 printf("[%02x] %08x %08x %08x ", i, w0, w1, w2);
2620                 if (w0 & PPC44x_TLB_VALID) {
2621                         printf("V %08x -> %01x%08x %c%c%c%c%c",
2622                                w0 & PPC44x_TLB_EPN_MASK,
2623                                w1 & PPC44x_TLB_ERPN_MASK,
2624                                w1 & PPC44x_TLB_RPN_MASK,
2625                                (w2 & PPC44x_TLB_W) ? 'W' : 'w',
2626                                (w2 & PPC44x_TLB_I) ? 'I' : 'i',
2627                                (w2 & PPC44x_TLB_M) ? 'M' : 'm',
2628                                (w2 & PPC44x_TLB_G) ? 'G' : 'g',
2629                                (w2 & PPC44x_TLB_E) ? 'E' : 'e');
2630                 }
2631                 printf("\n");
2632         }
2633 }
2634 #endif /* CONFIG_44x */
2635 void xmon_init(int enable)
2636 {
2637 #ifdef CONFIG_PPC_ISERIES
2638         if (firmware_has_feature(FW_FEATURE_ISERIES))
2639                 return;
2640 #endif
2641         if (enable) {
2642                 __debugger = xmon;
2643                 __debugger_ipi = xmon_ipi;
2644                 __debugger_bpt = xmon_bpt;
2645                 __debugger_sstep = xmon_sstep;
2646                 __debugger_iabr_match = xmon_iabr_match;
2647                 __debugger_dabr_match = xmon_dabr_match;
2648                 __debugger_fault_handler = xmon_fault_handler;
2649         } else {
2650                 __debugger = NULL;
2651                 __debugger_ipi = NULL;
2652                 __debugger_bpt = NULL;
2653                 __debugger_sstep = NULL;
2654                 __debugger_iabr_match = NULL;
2655                 __debugger_dabr_match = NULL;
2656                 __debugger_fault_handler = NULL;
2657         }
2658         xmon_map_scc();
2659 }
2660
2661 #ifdef CONFIG_MAGIC_SYSRQ
2662 static void sysrq_handle_xmon(int key, struct tty_struct *tty) 
2663 {
2664         /* ensure xmon is enabled */
2665         xmon_init(1);
2666         debugger(get_irq_regs());
2667 }
2668
2669 static struct sysrq_key_op sysrq_xmon_op = 
2670 {
2671         .handler =      sysrq_handle_xmon,
2672         .help_msg =     "Xmon",
2673         .action_msg =   "Entering xmon",
2674 };
2675
2676 static int __init setup_xmon_sysrq(void)
2677 {
2678 #ifdef CONFIG_PPC_ISERIES
2679         if (firmware_has_feature(FW_FEATURE_ISERIES))
2680                 return 0;
2681 #endif
2682         register_sysrq_key('x', &sysrq_xmon_op);
2683         return 0;
2684 }
2685 __initcall(setup_xmon_sysrq);
2686 #endif /* CONFIG_MAGIC_SYSRQ */
2687
2688 static int __initdata xmon_early, xmon_off;
2689
2690 static int __init early_parse_xmon(char *p)
2691 {
2692         if (!p || strncmp(p, "early", 5) == 0) {
2693                 /* just "xmon" is equivalent to "xmon=early" */
2694                 xmon_init(1);
2695                 xmon_early = 1;
2696         } else if (strncmp(p, "on", 2) == 0)
2697                 xmon_init(1);
2698         else if (strncmp(p, "off", 3) == 0)
2699                 xmon_off = 1;
2700         else if (strncmp(p, "nobt", 4) == 0)
2701                 xmon_no_auto_backtrace = 1;
2702         else
2703                 return 1;
2704
2705         return 0;
2706 }
2707 early_param("xmon", early_parse_xmon);
2708
2709 void __init xmon_setup(void)
2710 {
2711 #ifdef CONFIG_XMON_DEFAULT
2712         if (!xmon_off)
2713                 xmon_init(1);
2714 #endif
2715         if (xmon_early)
2716                 debugger(NULL);
2717 }
2718
2719 #ifdef CONFIG_SPU_BASE
2720
2721 struct spu_info {
2722         struct spu *spu;
2723         u64 saved_mfc_sr1_RW;
2724         u32 saved_spu_runcntl_RW;
2725         unsigned long dump_addr;
2726         u8 stopped_ok;
2727 };
2728
2729 #define XMON_NUM_SPUS   16      /* Enough for current hardware */
2730
2731 static struct spu_info spu_info[XMON_NUM_SPUS];
2732
2733 void xmon_register_spus(struct list_head *list)
2734 {
2735         struct spu *spu;
2736
2737         list_for_each_entry(spu, list, full_list) {
2738                 if (spu->number >= XMON_NUM_SPUS) {
2739                         WARN_ON(1);
2740                         continue;
2741                 }
2742
2743                 spu_info[spu->number].spu = spu;
2744                 spu_info[spu->number].stopped_ok = 0;
2745                 spu_info[spu->number].dump_addr = (unsigned long)
2746                                 spu_info[spu->number].spu->local_store;
2747         }
2748 }
2749
2750 static void stop_spus(void)
2751 {
2752         struct spu *spu;
2753         int i;
2754         u64 tmp;
2755
2756         for (i = 0; i < XMON_NUM_SPUS; i++) {
2757                 if (!spu_info[i].spu)
2758                         continue;
2759
2760                 if (setjmp(bus_error_jmp) == 0) {
2761                         catch_memory_errors = 1;
2762                         sync();
2763
2764                         spu = spu_info[i].spu;
2765
2766                         spu_info[i].saved_spu_runcntl_RW =
2767                                 in_be32(&spu->problem->spu_runcntl_RW);
2768
2769                         tmp = spu_mfc_sr1_get(spu);
2770                         spu_info[i].saved_mfc_sr1_RW = tmp;
2771
2772                         tmp &= ~MFC_STATE1_MASTER_RUN_CONTROL_MASK;
2773                         spu_mfc_sr1_set(spu, tmp);
2774
2775                         sync();
2776                         __delay(200);
2777
2778                         spu_info[i].stopped_ok = 1;
2779
2780                         printf("Stopped spu %.2d (was %s)\n", i,
2781                                         spu_info[i].saved_spu_runcntl_RW ?
2782                                         "running" : "stopped");
2783                 } else {
2784                         catch_memory_errors = 0;
2785                         printf("*** Error stopping spu %.2d\n", i);
2786                 }
2787                 catch_memory_errors = 0;
2788         }
2789 }
2790
2791 static void restart_spus(void)
2792 {
2793         struct spu *spu;
2794         int i;
2795
2796         for (i = 0; i < XMON_NUM_SPUS; i++) {
2797                 if (!spu_info[i].spu)
2798                         continue;
2799
2800                 if (!spu_info[i].stopped_ok) {
2801                         printf("*** Error, spu %d was not successfully stopped"
2802                                         ", not restarting\n", i);
2803                         continue;
2804                 }
2805
2806                 if (setjmp(bus_error_jmp) == 0) {
2807                         catch_memory_errors = 1;
2808                         sync();
2809
2810                         spu = spu_info[i].spu;
2811                         spu_mfc_sr1_set(spu, spu_info[i].saved_mfc_sr1_RW);
2812                         out_be32(&spu->problem->spu_runcntl_RW,
2813                                         spu_info[i].saved_spu_runcntl_RW);
2814
2815                         sync();
2816                         __delay(200);
2817
2818                         printf("Restarted spu %.2d\n", i);
2819                 } else {
2820                         catch_memory_errors = 0;
2821                         printf("*** Error restarting spu %.2d\n", i);
2822                 }
2823                 catch_memory_errors = 0;
2824         }
2825 }
2826
2827 #define DUMP_WIDTH      23
2828 #define DUMP_VALUE(format, field, value)                                \
2829 do {                                                                    \
2830         if (setjmp(bus_error_jmp) == 0) {                               \
2831                 catch_memory_errors = 1;                                \
2832                 sync();                                                 \
2833                 printf("  %-*s = "format"\n", DUMP_WIDTH,               \
2834                                 #field, value);                         \
2835                 sync();                                                 \
2836                 __delay(200);                                           \
2837         } else {                                                        \
2838                 catch_memory_errors = 0;                                \
2839                 printf("  %-*s = *** Error reading field.\n",           \
2840                                         DUMP_WIDTH, #field);            \
2841         }                                                               \
2842         catch_memory_errors = 0;                                        \
2843 } while (0)
2844
2845 #define DUMP_FIELD(obj, format, field)  \
2846         DUMP_VALUE(format, field, obj->field)
2847
2848 static void dump_spu_fields(struct spu *spu)
2849 {
2850         printf("Dumping spu fields at address %p:\n", spu);
2851
2852         DUMP_FIELD(spu, "0x%x", number);
2853         DUMP_FIELD(spu, "%s", name);
2854         DUMP_FIELD(spu, "0x%lx", local_store_phys);
2855         DUMP_FIELD(spu, "0x%p", local_store);
2856         DUMP_FIELD(spu, "0x%lx", ls_size);
2857         DUMP_FIELD(spu, "0x%x", node);
2858         DUMP_FIELD(spu, "0x%lx", flags);
2859         DUMP_FIELD(spu, "0x%lx", dar);
2860         DUMP_FIELD(spu, "0x%lx", dsisr);
2861         DUMP_FIELD(spu, "%d", class_0_pending);
2862         DUMP_FIELD(spu, "0x%lx", irqs[0]);
2863         DUMP_FIELD(spu, "0x%lx", irqs[1]);
2864         DUMP_FIELD(spu, "0x%lx", irqs[2]);
2865         DUMP_FIELD(spu, "0x%x", slb_replace);
2866         DUMP_FIELD(spu, "%d", pid);
2867         DUMP_FIELD(spu, "0x%p", mm);
2868         DUMP_FIELD(spu, "0x%p", ctx);
2869         DUMP_FIELD(spu, "0x%p", rq);
2870         DUMP_FIELD(spu, "0x%p", timestamp);
2871         DUMP_FIELD(spu, "0x%lx", problem_phys);
2872         DUMP_FIELD(spu, "0x%p", problem);
2873         DUMP_VALUE("0x%x", problem->spu_runcntl_RW,
2874                         in_be32(&spu->problem->spu_runcntl_RW));
2875         DUMP_VALUE("0x%x", problem->spu_status_R,
2876                         in_be32(&spu->problem->spu_status_R));
2877         DUMP_VALUE("0x%x", problem->spu_npc_RW,
2878                         in_be32(&spu->problem->spu_npc_RW));
2879         DUMP_FIELD(spu, "0x%p", priv2);
2880         DUMP_FIELD(spu, "0x%p", pdata);
2881 }
2882
2883 int
2884 spu_inst_dump(unsigned long adr, long count, int praddr)
2885 {
2886         return generic_inst_dump(adr, count, praddr, print_insn_spu);
2887 }
2888
2889 static void dump_spu_ls(unsigned long num, int subcmd)
2890 {
2891         unsigned long offset, addr, ls_addr;
2892
2893         if (setjmp(bus_error_jmp) == 0) {
2894                 catch_memory_errors = 1;
2895                 sync();
2896                 ls_addr = (unsigned long)spu_info[num].spu->local_store;
2897                 sync();
2898                 __delay(200);
2899         } else {
2900                 catch_memory_errors = 0;
2901                 printf("*** Error: accessing spu info for spu %d\n", num);
2902                 return;
2903         }
2904         catch_memory_errors = 0;
2905
2906         if (scanhex(&offset))
2907                 addr = ls_addr + offset;
2908         else
2909                 addr = spu_info[num].dump_addr;
2910
2911         if (addr >= ls_addr + LS_SIZE) {
2912                 printf("*** Error: address outside of local store\n");
2913                 return;
2914         }
2915
2916         switch (subcmd) {
2917         case 'i':
2918                 addr += spu_inst_dump(addr, 16, 1);
2919                 last_cmd = "sdi\n";
2920                 break;
2921         default:
2922                 prdump(addr, 64);
2923                 addr += 64;
2924                 last_cmd = "sd\n";
2925                 break;
2926         }
2927
2928         spu_info[num].dump_addr = addr;
2929 }
2930
2931 static int do_spu_cmd(void)
2932 {
2933         static unsigned long num = 0;
2934         int cmd, subcmd = 0;
2935
2936         cmd = inchar();
2937         switch (cmd) {
2938         case 's':
2939                 stop_spus();
2940                 break;
2941         case 'r':
2942                 restart_spus();
2943                 break;
2944         case 'd':
2945                 subcmd = inchar();
2946                 if (isxdigit(subcmd) || subcmd == '\n')
2947                         termch = subcmd;
2948         case 'f':
2949                 scanhex(&num);
2950                 if (num >= XMON_NUM_SPUS || !spu_info[num].spu) {
2951                         printf("*** Error: invalid spu number\n");
2952                         return 0;
2953                 }
2954
2955                 switch (cmd) {
2956                 case 'f':
2957                         dump_spu_fields(spu_info[num].spu);
2958                         break;
2959                 default:
2960                         dump_spu_ls(num, subcmd);
2961                         break;
2962                 }
2963
2964                 break;
2965         default:
2966                 return -1;
2967         }
2968
2969         return 0;
2970 }
2971 #else /* ! CONFIG_SPU_BASE */
2972 static int do_spu_cmd(void)
2973 {
2974         return -1;
2975 }
2976 #endif