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