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