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