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