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