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