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