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