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