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