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