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