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