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