Linux 3.4
[linux-flexiantxendom0-3.2.10.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/setjmp.h>
43 #include <asm/reg.h>
44 #include <asm/debug.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\t softe: %d\t irq_happened: 0x%02x\n",
1441                local_paca, local_paca->soft_enabled, local_paca->irq_happened);
1442 #endif
1443         if (current) {
1444                 printf("    pid   = %ld, comm = %s\n",
1445                        current->pid, current->comm);
1446         }
1447
1448         if (trap == 0x700)
1449                 print_bug_trap(fp);
1450 }
1451
1452 static void prregs(struct pt_regs *fp)
1453 {
1454         int n, trap;
1455         unsigned long base;
1456         struct pt_regs regs;
1457
1458         if (scanhex(&base)) {
1459                 if (setjmp(bus_error_jmp) == 0) {
1460                         catch_memory_errors = 1;
1461                         sync();
1462                         regs = *(struct pt_regs *)base;
1463                         sync();
1464                         __delay(200);
1465                 } else {
1466                         catch_memory_errors = 0;
1467                         printf("*** Error reading registers from "REG"\n",
1468                                base);
1469                         return;
1470                 }
1471                 catch_memory_errors = 0;
1472                 fp = &regs;
1473         }
1474
1475 #ifdef CONFIG_PPC64
1476         if (FULL_REGS(fp)) {
1477                 for (n = 0; n < 16; ++n)
1478                         printf("R%.2ld = "REG"   R%.2ld = "REG"\n",
1479                                n, fp->gpr[n], n+16, fp->gpr[n+16]);
1480         } else {
1481                 for (n = 0; n < 7; ++n)
1482                         printf("R%.2ld = "REG"   R%.2ld = "REG"\n",
1483                                n, fp->gpr[n], n+7, fp->gpr[n+7]);
1484         }
1485 #else
1486         for (n = 0; n < 32; ++n) {
1487                 printf("R%.2d = %.8x%s", n, fp->gpr[n],
1488                        (n & 3) == 3? "\n": "   ");
1489                 if (n == 12 && !FULL_REGS(fp)) {
1490                         printf("\n");
1491                         break;
1492                 }
1493         }
1494 #endif
1495         printf("pc  = ");
1496         xmon_print_symbol(fp->nip, " ", "\n");
1497         if (TRAP(fp) != 0xc00 && cpu_has_feature(CPU_FTR_CFAR)) {
1498                 printf("cfar= ");
1499                 xmon_print_symbol(fp->orig_gpr3, " ", "\n");
1500         }
1501         printf("lr  = ");
1502         xmon_print_symbol(fp->link, " ", "\n");
1503         printf("msr = "REG"   cr  = %.8lx\n", fp->msr, fp->ccr);
1504         printf("ctr = "REG"   xer = "REG"   trap = %4lx\n",
1505                fp->ctr, fp->xer, fp->trap);
1506         trap = TRAP(fp);
1507         if (trap == 0x300 || trap == 0x380 || trap == 0x600)
1508                 printf("dar = "REG"   dsisr = %.8lx\n", fp->dar, fp->dsisr);
1509 }
1510
1511 static void cacheflush(void)
1512 {
1513         int cmd;
1514         unsigned long nflush;
1515
1516         cmd = inchar();
1517         if (cmd != 'i')
1518                 termch = cmd;
1519         scanhex((void *)&adrs);
1520         if (termch != '\n')
1521                 termch = 0;
1522         nflush = 1;
1523         scanhex(&nflush);
1524         nflush = (nflush + L1_CACHE_BYTES - 1) / L1_CACHE_BYTES;
1525         if (setjmp(bus_error_jmp) == 0) {
1526                 catch_memory_errors = 1;
1527                 sync();
1528
1529                 if (cmd != 'i') {
1530                         for (; nflush > 0; --nflush, adrs += L1_CACHE_BYTES)
1531                                 cflush((void *) adrs);
1532                 } else {
1533                         for (; nflush > 0; --nflush, adrs += L1_CACHE_BYTES)
1534                                 cinval((void *) adrs);
1535                 }
1536                 sync();
1537                 /* wait a little while to see if we get a machine check */
1538                 __delay(200);
1539         }
1540         catch_memory_errors = 0;
1541 }
1542
1543 static unsigned long
1544 read_spr(int n)
1545 {
1546         unsigned int instrs[2];
1547         unsigned long (*code)(void);
1548         unsigned long ret = -1UL;
1549 #ifdef CONFIG_PPC64
1550         unsigned long opd[3];
1551
1552         opd[0] = (unsigned long)instrs;
1553         opd[1] = 0;
1554         opd[2] = 0;
1555         code = (unsigned long (*)(void)) opd;
1556 #else
1557         code = (unsigned long (*)(void)) instrs;
1558 #endif
1559
1560         /* mfspr r3,n; blr */
1561         instrs[0] = 0x7c6002a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
1562         instrs[1] = 0x4e800020;
1563         store_inst(instrs);
1564         store_inst(instrs+1);
1565
1566         if (setjmp(bus_error_jmp) == 0) {
1567                 catch_memory_errors = 1;
1568                 sync();
1569
1570                 ret = code();
1571
1572                 sync();
1573                 /* wait a little while to see if we get a machine check */
1574                 __delay(200);
1575                 n = size;
1576         }
1577
1578         return ret;
1579 }
1580
1581 static void
1582 write_spr(int n, unsigned long val)
1583 {
1584         unsigned int instrs[2];
1585         unsigned long (*code)(unsigned long);
1586 #ifdef CONFIG_PPC64
1587         unsigned long opd[3];
1588
1589         opd[0] = (unsigned long)instrs;
1590         opd[1] = 0;
1591         opd[2] = 0;
1592         code = (unsigned long (*)(unsigned long)) opd;
1593 #else
1594         code = (unsigned long (*)(unsigned long)) instrs;
1595 #endif
1596
1597         instrs[0] = 0x7c6003a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
1598         instrs[1] = 0x4e800020;
1599         store_inst(instrs);
1600         store_inst(instrs+1);
1601
1602         if (setjmp(bus_error_jmp) == 0) {
1603                 catch_memory_errors = 1;
1604                 sync();
1605
1606                 code(val);
1607
1608                 sync();
1609                 /* wait a little while to see if we get a machine check */
1610                 __delay(200);
1611                 n = size;
1612         }
1613 }
1614
1615 static unsigned long regno;
1616 extern char exc_prolog;
1617 extern char dec_exc;
1618
1619 static void super_regs(void)
1620 {
1621         int cmd;
1622         unsigned long val;
1623
1624         cmd = skipbl();
1625         if (cmd == '\n') {
1626                 unsigned long sp, toc;
1627                 asm("mr %0,1" : "=r" (sp) :);
1628                 asm("mr %0,2" : "=r" (toc) :);
1629
1630                 printf("msr  = "REG"  sprg0= "REG"\n",
1631                        mfmsr(), mfspr(SPRN_SPRG0));
1632                 printf("pvr  = "REG"  sprg1= "REG"\n",
1633                        mfspr(SPRN_PVR), mfspr(SPRN_SPRG1)); 
1634                 printf("dec  = "REG"  sprg2= "REG"\n",
1635                        mfspr(SPRN_DEC), mfspr(SPRN_SPRG2));
1636                 printf("sp   = "REG"  sprg3= "REG"\n", sp, mfspr(SPRN_SPRG3));
1637                 printf("toc  = "REG"  dar  = "REG"\n", toc, mfspr(SPRN_DAR));
1638
1639                 return;
1640         }
1641
1642         scanhex(&regno);
1643         switch (cmd) {
1644         case 'w':
1645                 val = read_spr(regno);
1646                 scanhex(&val);
1647                 write_spr(regno, val);
1648                 /* fall through */
1649         case 'r':
1650                 printf("spr %lx = %lx\n", regno, read_spr(regno));
1651                 break;
1652         }
1653         scannl();
1654 }
1655
1656 /*
1657  * Stuff for reading and writing memory safely
1658  */
1659 static int
1660 mread(unsigned long adrs, void *buf, int size)
1661 {
1662         volatile int n;
1663         char *p, *q;
1664
1665         n = 0;
1666         if (setjmp(bus_error_jmp) == 0) {
1667                 catch_memory_errors = 1;
1668                 sync();
1669                 p = (char *)adrs;
1670                 q = (char *)buf;
1671                 switch (size) {
1672                 case 2:
1673                         *(u16 *)q = *(u16 *)p;
1674                         break;
1675                 case 4:
1676                         *(u32 *)q = *(u32 *)p;
1677                         break;
1678                 case 8:
1679                         *(u64 *)q = *(u64 *)p;
1680                         break;
1681                 default:
1682                         for( ; n < size; ++n) {
1683                                 *q++ = *p++;
1684                                 sync();
1685                         }
1686                 }
1687                 sync();
1688                 /* wait a little while to see if we get a machine check */
1689                 __delay(200);
1690                 n = size;
1691         }
1692         catch_memory_errors = 0;
1693         return n;
1694 }
1695
1696 static int
1697 mwrite(unsigned long adrs, void *buf, int size)
1698 {
1699         volatile int n;
1700         char *p, *q;
1701
1702         n = 0;
1703         if (setjmp(bus_error_jmp) == 0) {
1704                 catch_memory_errors = 1;
1705                 sync();
1706                 p = (char *) adrs;
1707                 q = (char *) buf;
1708                 switch (size) {
1709                 case 2:
1710                         *(u16 *)p = *(u16 *)q;
1711                         break;
1712                 case 4:
1713                         *(u32 *)p = *(u32 *)q;
1714                         break;
1715                 case 8:
1716                         *(u64 *)p = *(u64 *)q;
1717                         break;
1718                 default:
1719                         for ( ; n < size; ++n) {
1720                                 *p++ = *q++;
1721                                 sync();
1722                         }
1723                 }
1724                 sync();
1725                 /* wait a little while to see if we get a machine check */
1726                 __delay(200);
1727                 n = size;
1728         } else {
1729                 printf("*** Error writing address %x\n", adrs + n);
1730         }
1731         catch_memory_errors = 0;
1732         return n;
1733 }
1734
1735 static int fault_type;
1736 static int fault_except;
1737 static char *fault_chars[] = { "--", "**", "##" };
1738
1739 static int handle_fault(struct pt_regs *regs)
1740 {
1741         fault_except = TRAP(regs);
1742         switch (TRAP(regs)) {
1743         case 0x200:
1744                 fault_type = 0;
1745                 break;
1746         case 0x300:
1747         case 0x380:
1748                 fault_type = 1;
1749                 break;
1750         default:
1751                 fault_type = 2;
1752         }
1753
1754         longjmp(bus_error_jmp, 1);
1755
1756         return 0;
1757 }
1758
1759 #define SWAP(a, b, t)   ((t) = (a), (a) = (b), (b) = (t))
1760
1761 static void
1762 byterev(unsigned char *val, int size)
1763 {
1764         int t;
1765         
1766         switch (size) {
1767         case 2:
1768                 SWAP(val[0], val[1], t);
1769                 break;
1770         case 4:
1771                 SWAP(val[0], val[3], t);
1772                 SWAP(val[1], val[2], t);
1773                 break;
1774         case 8: /* is there really any use for this? */
1775                 SWAP(val[0], val[7], t);
1776                 SWAP(val[1], val[6], t);
1777                 SWAP(val[2], val[5], t);
1778                 SWAP(val[3], val[4], t);
1779                 break;
1780         }
1781 }
1782
1783 static int brev;
1784 static int mnoread;
1785
1786 static char *memex_help_string = 
1787     "Memory examine command usage:\n"
1788     "m [addr] [flags] examine/change memory\n"
1789     "  addr is optional.  will start where left off.\n"
1790     "  flags may include chars from this set:\n"
1791     "    b   modify by bytes (default)\n"
1792     "    w   modify by words (2 byte)\n"
1793     "    l   modify by longs (4 byte)\n"
1794     "    d   modify by doubleword (8 byte)\n"
1795     "    r   toggle reverse byte order mode\n"
1796     "    n   do not read memory (for i/o spaces)\n"
1797     "    .   ok to read (default)\n"
1798     "NOTE: flags are saved as defaults\n"
1799     "";
1800
1801 static char *memex_subcmd_help_string = 
1802     "Memory examine subcommands:\n"
1803     "  hexval   write this val to current location\n"
1804     "  'string' write chars from string to this location\n"
1805     "  '        increment address\n"
1806     "  ^        decrement address\n"
1807     "  /        increment addr by 0x10.  //=0x100, ///=0x1000, etc\n"
1808     "  \\        decrement addr by 0x10.  \\\\=0x100, \\\\\\=0x1000, etc\n"
1809     "  `        clear no-read flag\n"
1810     "  ;        stay at this addr\n"
1811     "  v        change to byte mode\n"
1812     "  w        change to word (2 byte) mode\n"
1813     "  l        change to long (4 byte) mode\n"
1814     "  u        change to doubleword (8 byte) mode\n"
1815     "  m addr   change current addr\n"
1816     "  n        toggle no-read flag\n"
1817     "  r        toggle byte reverse flag\n"
1818     "  < count  back up count bytes\n"
1819     "  > count  skip forward count bytes\n"
1820     "  x        exit this mode\n"
1821     "";
1822
1823 static void
1824 memex(void)
1825 {
1826         int cmd, inc, i, nslash;
1827         unsigned long n;
1828         unsigned char val[16];
1829
1830         scanhex((void *)&adrs);
1831         cmd = skipbl();
1832         if (cmd == '?') {
1833                 printf(memex_help_string);
1834                 return;
1835         } else {
1836                 termch = cmd;
1837         }
1838         last_cmd = "m\n";
1839         while ((cmd = skipbl()) != '\n') {
1840                 switch( cmd ){
1841                 case 'b':       size = 1;       break;
1842                 case 'w':       size = 2;       break;
1843                 case 'l':       size = 4;       break;
1844                 case 'd':       size = 8;       break;
1845                 case 'r':       brev = !brev;   break;
1846                 case 'n':       mnoread = 1;    break;
1847                 case '.':       mnoread = 0;    break;
1848                 }
1849         }
1850         if( size <= 0 )
1851                 size = 1;
1852         else if( size > 8 )
1853                 size = 8;
1854         for(;;){
1855                 if (!mnoread)
1856                         n = mread(adrs, val, size);
1857                 printf(REG"%c", adrs, brev? 'r': ' ');
1858                 if (!mnoread) {
1859                         if (brev)
1860                                 byterev(val, size);
1861                         putchar(' ');
1862                         for (i = 0; i < n; ++i)
1863                                 printf("%.2x", val[i]);
1864                         for (; i < size; ++i)
1865                                 printf("%s", fault_chars[fault_type]);
1866                 }
1867                 putchar(' ');
1868                 inc = size;
1869                 nslash = 0;
1870                 for(;;){
1871                         if( scanhex(&n) ){
1872                                 for (i = 0; i < size; ++i)
1873                                         val[i] = n >> (i * 8);
1874                                 if (!brev)
1875                                         byterev(val, size);
1876                                 mwrite(adrs, val, size);
1877                                 inc = size;
1878                         }
1879                         cmd = skipbl();
1880                         if (cmd == '\n')
1881                                 break;
1882                         inc = 0;
1883                         switch (cmd) {
1884                         case '\'':
1885                                 for(;;){
1886                                         n = inchar();
1887                                         if( n == '\\' )
1888                                                 n = bsesc();
1889                                         else if( n == '\'' )
1890                                                 break;
1891                                         for (i = 0; i < size; ++i)
1892                                                 val[i] = n >> (i * 8);
1893                                         if (!brev)
1894                                                 byterev(val, size);
1895                                         mwrite(adrs, val, size);
1896                                         adrs += size;
1897                                 }
1898                                 adrs -= size;
1899                                 inc = size;
1900                                 break;
1901                         case ',':
1902                                 adrs += size;
1903                                 break;
1904                         case '.':
1905                                 mnoread = 0;
1906                                 break;
1907                         case ';':
1908                                 break;
1909                         case 'x':
1910                         case EOF:
1911                                 scannl();
1912                                 return;
1913                         case 'b':
1914                         case 'v':
1915                                 size = 1;
1916                                 break;
1917                         case 'w':
1918                                 size = 2;
1919                                 break;
1920                         case 'l':
1921                                 size = 4;
1922                                 break;
1923                         case 'u':
1924                                 size = 8;
1925                                 break;
1926                         case '^':
1927                                 adrs -= size;
1928                                 break;
1929                                 break;
1930                         case '/':
1931                                 if (nslash > 0)
1932                                         adrs -= 1 << nslash;
1933                                 else
1934                                         nslash = 0;
1935                                 nslash += 4;
1936                                 adrs += 1 << nslash;
1937                                 break;
1938                         case '\\':
1939                                 if (nslash < 0)
1940                                         adrs += 1 << -nslash;
1941                                 else
1942                                         nslash = 0;
1943                                 nslash -= 4;
1944                                 adrs -= 1 << -nslash;
1945                                 break;
1946                         case 'm':
1947                                 scanhex((void *)&adrs);
1948                                 break;
1949                         case 'n':
1950                                 mnoread = 1;
1951                                 break;
1952                         case 'r':
1953                                 brev = !brev;
1954                                 break;
1955                         case '<':
1956                                 n = size;
1957                                 scanhex(&n);
1958                                 adrs -= n;
1959                                 break;
1960                         case '>':
1961                                 n = size;
1962                                 scanhex(&n);
1963                                 adrs += n;
1964                                 break;
1965                         case '?':
1966                                 printf(memex_subcmd_help_string);
1967                                 break;
1968                         }
1969                 }
1970                 adrs += inc;
1971         }
1972 }
1973
1974 static int
1975 bsesc(void)
1976 {
1977         int c;
1978
1979         c = inchar();
1980         switch( c ){
1981         case 'n':       c = '\n';       break;
1982         case 'r':       c = '\r';       break;
1983         case 'b':       c = '\b';       break;
1984         case 't':       c = '\t';       break;
1985         }
1986         return c;
1987 }
1988
1989 static void xmon_rawdump (unsigned long adrs, long ndump)
1990 {
1991         long n, m, r, nr;
1992         unsigned char temp[16];
1993
1994         for (n = ndump; n > 0;) {
1995                 r = n < 16? n: 16;
1996                 nr = mread(adrs, temp, r);
1997                 adrs += nr;
1998                 for (m = 0; m < r; ++m) {
1999                         if (m < nr)
2000                                 printf("%.2x", temp[m]);
2001                         else
2002                                 printf("%s", fault_chars[fault_type]);
2003                 }
2004                 n -= r;
2005                 if (nr < r)
2006                         break;
2007         }
2008         printf("\n");
2009 }
2010
2011 #define isxdigit(c)     (('0' <= (c) && (c) <= '9') \
2012                          || ('a' <= (c) && (c) <= 'f') \
2013                          || ('A' <= (c) && (c) <= 'F'))
2014 static void
2015 dump(void)
2016 {
2017         int c;
2018
2019         c = inchar();
2020         if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')
2021                 termch = c;
2022         scanhex((void *)&adrs);
2023         if (termch != '\n')
2024                 termch = 0;
2025         if (c == 'i') {
2026                 scanhex(&nidump);
2027                 if (nidump == 0)
2028                         nidump = 16;
2029                 else if (nidump > MAX_DUMP)
2030                         nidump = MAX_DUMP;
2031                 adrs += ppc_inst_dump(adrs, nidump, 1);
2032                 last_cmd = "di\n";
2033         } else if (c == 'l') {
2034                 dump_log_buf();
2035         } else if (c == 'r') {
2036                 scanhex(&ndump);
2037                 if (ndump == 0)
2038                         ndump = 64;
2039                 xmon_rawdump(adrs, ndump);
2040                 adrs += ndump;
2041                 last_cmd = "dr\n";
2042         } else {
2043                 scanhex(&ndump);
2044                 if (ndump == 0)
2045                         ndump = 64;
2046                 else if (ndump > MAX_DUMP)
2047                         ndump = MAX_DUMP;
2048                 prdump(adrs, ndump);
2049                 adrs += ndump;
2050                 last_cmd = "d\n";
2051         }
2052 }
2053
2054 static void
2055 prdump(unsigned long adrs, long ndump)
2056 {
2057         long n, m, c, r, nr;
2058         unsigned char temp[16];
2059
2060         for (n = ndump; n > 0;) {
2061                 printf(REG, adrs);
2062                 putchar(' ');
2063                 r = n < 16? n: 16;
2064                 nr = mread(adrs, temp, r);
2065                 adrs += nr;
2066                 for (m = 0; m < r; ++m) {
2067                         if ((m & (sizeof(long) - 1)) == 0 && m > 0)
2068                                 putchar(' ');
2069                         if (m < nr)
2070                                 printf("%.2x", temp[m]);
2071                         else
2072                                 printf("%s", fault_chars[fault_type]);
2073                 }
2074                 for (; m < 16; ++m) {
2075                         if ((m & (sizeof(long) - 1)) == 0)
2076                                 putchar(' ');
2077                         printf("  ");
2078                 }
2079                 printf("  |");
2080                 for (m = 0; m < r; ++m) {
2081                         if (m < nr) {
2082                                 c = temp[m];
2083                                 putchar(' ' <= c && c <= '~'? c: '.');
2084                         } else
2085                                 putchar(' ');
2086                 }
2087                 n -= r;
2088                 for (; m < 16; ++m)
2089                         putchar(' ');
2090                 printf("|\n");
2091                 if (nr < r)
2092                         break;
2093         }
2094 }
2095
2096 typedef int (*instruction_dump_func)(unsigned long inst, unsigned long addr);
2097
2098 static int
2099 generic_inst_dump(unsigned long adr, long count, int praddr,
2100                         instruction_dump_func dump_func)
2101 {
2102         int nr, dotted;
2103         unsigned long first_adr;
2104         unsigned long inst, last_inst = 0;
2105         unsigned char val[4];
2106
2107         dotted = 0;
2108         for (first_adr = adr; count > 0; --count, adr += 4) {
2109                 nr = mread(adr, val, 4);
2110                 if (nr == 0) {
2111                         if (praddr) {
2112                                 const char *x = fault_chars[fault_type];
2113                                 printf(REG"  %s%s%s%s\n", adr, x, x, x, x);
2114                         }
2115                         break;
2116                 }
2117                 inst = GETWORD(val);
2118                 if (adr > first_adr && inst == last_inst) {
2119                         if (!dotted) {
2120                                 printf(" ...\n");
2121                                 dotted = 1;
2122                         }
2123                         continue;
2124                 }
2125                 dotted = 0;
2126                 last_inst = inst;
2127                 if (praddr)
2128                         printf(REG"  %.8x", adr, inst);
2129                 printf("\t");
2130                 dump_func(inst, adr);
2131                 printf("\n");
2132         }
2133         return adr - first_adr;
2134 }
2135
2136 static int
2137 ppc_inst_dump(unsigned long adr, long count, int praddr)
2138 {
2139         return generic_inst_dump(adr, count, praddr, print_insn_powerpc);
2140 }
2141
2142 void
2143 print_address(unsigned long addr)
2144 {
2145         xmon_print_symbol(addr, "\t# ", "");
2146 }
2147
2148 void
2149 dump_log_buf(void)
2150 {
2151         const unsigned long size = 128;
2152         unsigned long end, addr;
2153         unsigned char buf[size + 1];
2154
2155         addr = 0;
2156         buf[size] = '\0';
2157
2158         if (setjmp(bus_error_jmp) != 0) {
2159                 printf("Unable to lookup symbol __log_buf!\n");
2160                 return;
2161         }
2162
2163         catch_memory_errors = 1;
2164         sync();
2165         addr = kallsyms_lookup_name("__log_buf");
2166
2167         if (! addr)
2168                 printf("Symbol __log_buf not found!\n");
2169         else {
2170                 end = addr + (1 << CONFIG_LOG_BUF_SHIFT);
2171                 while (addr < end) {
2172                         if (! mread(addr, buf, size)) {
2173                                 printf("Can't read memory at address 0x%lx\n", addr);
2174                                 break;
2175                         }
2176
2177                         printf("%s", buf);
2178
2179                         if (strlen(buf) < size)
2180                                 break;
2181
2182                         addr += size;
2183                 }
2184         }
2185
2186         sync();
2187         /* wait a little while to see if we get a machine check */
2188         __delay(200);
2189         catch_memory_errors = 0;
2190 }
2191
2192 /*
2193  * Memory operations - move, set, print differences
2194  */
2195 static unsigned long mdest;             /* destination address */
2196 static unsigned long msrc;              /* source address */
2197 static unsigned long mval;              /* byte value to set memory to */
2198 static unsigned long mcount;            /* # bytes to affect */
2199 static unsigned long mdiffs;            /* max # differences to print */
2200
2201 static void
2202 memops(int cmd)
2203 {
2204         scanhex((void *)&mdest);
2205         if( termch != '\n' )
2206                 termch = 0;
2207         scanhex((void *)(cmd == 's'? &mval: &msrc));
2208         if( termch != '\n' )
2209                 termch = 0;
2210         scanhex((void *)&mcount);
2211         switch( cmd ){
2212         case 'm':
2213                 memmove((void *)mdest, (void *)msrc, mcount);
2214                 break;
2215         case 's':
2216                 memset((void *)mdest, mval, mcount);
2217                 break;
2218         case 'd':
2219                 if( termch != '\n' )
2220                         termch = 0;
2221                 scanhex((void *)&mdiffs);
2222                 memdiffs((unsigned char *)mdest, (unsigned char *)msrc, mcount, mdiffs);
2223                 break;
2224         }
2225 }
2226
2227 static void
2228 memdiffs(unsigned char *p1, unsigned char *p2, unsigned nb, unsigned maxpr)
2229 {
2230         unsigned n, prt;
2231
2232         prt = 0;
2233         for( n = nb; n > 0; --n )
2234                 if( *p1++ != *p2++ )
2235                         if( ++prt <= maxpr )
2236                                 printf("%.16x %.2x # %.16x %.2x\n", p1 - 1,
2237                                         p1[-1], p2 - 1, p2[-1]);
2238         if( prt > maxpr )
2239                 printf("Total of %d differences\n", prt);
2240 }
2241
2242 static unsigned mend;
2243 static unsigned mask;
2244
2245 static void
2246 memlocate(void)
2247 {
2248         unsigned a, n;
2249         unsigned char val[4];
2250
2251         last_cmd = "ml";
2252         scanhex((void *)&mdest);
2253         if (termch != '\n') {
2254                 termch = 0;
2255                 scanhex((void *)&mend);
2256                 if (termch != '\n') {
2257                         termch = 0;
2258                         scanhex((void *)&mval);
2259                         mask = ~0;
2260                         if (termch != '\n') termch = 0;
2261                         scanhex((void *)&mask);
2262                 }
2263         }
2264         n = 0;
2265         for (a = mdest; a < mend; a += 4) {
2266                 if (mread(a, val, 4) == 4
2267                         && ((GETWORD(val) ^ mval) & mask) == 0) {
2268                         printf("%.16x:  %.16x\n", a, GETWORD(val));
2269                         if (++n >= 10)
2270                                 break;
2271                 }
2272         }
2273 }
2274
2275 static unsigned long mskip = 0x1000;
2276 static unsigned long mlim = 0xffffffff;
2277
2278 static void
2279 memzcan(void)
2280 {
2281         unsigned char v;
2282         unsigned a;
2283         int ok, ook;
2284
2285         scanhex(&mdest);
2286         if (termch != '\n') termch = 0;
2287         scanhex(&mskip);
2288         if (termch != '\n') termch = 0;
2289         scanhex(&mlim);
2290         ook = 0;
2291         for (a = mdest; a < mlim; a += mskip) {
2292                 ok = mread(a, &v, 1);
2293                 if (ok && !ook) {
2294                         printf("%.8x .. ", a);
2295                 } else if (!ok && ook)
2296                         printf("%.8x\n", a - mskip);
2297                 ook = ok;
2298                 if (a + mskip < a)
2299                         break;
2300         }
2301         if (ook)
2302                 printf("%.8x\n", a - mskip);
2303 }
2304
2305 static void proccall(void)
2306 {
2307         unsigned long args[8];
2308         unsigned long ret;
2309         int i;
2310         typedef unsigned long (*callfunc_t)(unsigned long, unsigned long,
2311                         unsigned long, unsigned long, unsigned long,
2312                         unsigned long, unsigned long, unsigned long);
2313         callfunc_t func;
2314
2315         if (!scanhex(&adrs))
2316                 return;
2317         if (termch != '\n')
2318                 termch = 0;
2319         for (i = 0; i < 8; ++i)
2320                 args[i] = 0;
2321         for (i = 0; i < 8; ++i) {
2322                 if (!scanhex(&args[i]) || termch == '\n')
2323                         break;
2324                 termch = 0;
2325         }
2326         func = (callfunc_t) adrs;
2327         ret = 0;
2328         if (setjmp(bus_error_jmp) == 0) {
2329                 catch_memory_errors = 1;
2330                 sync();
2331                 ret = func(args[0], args[1], args[2], args[3],
2332                            args[4], args[5], args[6], args[7]);
2333                 sync();
2334                 printf("return value is %x\n", ret);
2335         } else {
2336                 printf("*** %x exception occurred\n", fault_except);
2337         }
2338         catch_memory_errors = 0;
2339 }
2340
2341 /* Input scanning routines */
2342 int
2343 skipbl(void)
2344 {
2345         int c;
2346
2347         if( termch != 0 ){
2348                 c = termch;
2349                 termch = 0;
2350         } else
2351                 c = inchar();
2352         while( c == ' ' || c == '\t' )
2353                 c = inchar();
2354         return c;
2355 }
2356
2357 #define N_PTREGS        44
2358 static char *regnames[N_PTREGS] = {
2359         "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
2360         "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
2361         "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
2362         "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
2363         "pc", "msr", "or3", "ctr", "lr", "xer", "ccr",
2364 #ifdef CONFIG_PPC64
2365         "softe",
2366 #else
2367         "mq",
2368 #endif
2369         "trap", "dar", "dsisr", "res"
2370 };
2371
2372 int
2373 scanhex(unsigned long *vp)
2374 {
2375         int c, d;
2376         unsigned long v;
2377
2378         c = skipbl();
2379         if (c == '%') {
2380                 /* parse register name */
2381                 char regname[8];
2382                 int i;
2383
2384                 for (i = 0; i < sizeof(regname) - 1; ++i) {
2385                         c = inchar();
2386                         if (!isalnum(c)) {
2387                                 termch = c;
2388                                 break;
2389                         }
2390                         regname[i] = c;
2391                 }
2392                 regname[i] = 0;
2393                 for (i = 0; i < N_PTREGS; ++i) {
2394                         if (strcmp(regnames[i], regname) == 0) {
2395                                 if (xmon_regs == NULL) {
2396                                         printf("regs not available\n");
2397                                         return 0;
2398                                 }
2399                                 *vp = ((unsigned long *)xmon_regs)[i];
2400                                 return 1;
2401                         }
2402                 }
2403                 printf("invalid register name '%%%s'\n", regname);
2404                 return 0;
2405         }
2406
2407         /* skip leading "0x" if any */
2408
2409         if (c == '0') {
2410                 c = inchar();
2411                 if (c == 'x') {
2412                         c = inchar();
2413                 } else {
2414                         d = hexdigit(c);
2415                         if (d == EOF) {
2416                                 termch = c;
2417                                 *vp = 0;
2418                                 return 1;
2419                         }
2420                 }
2421         } else if (c == '$') {
2422                 int i;
2423                 for (i=0; i<63; i++) {
2424                         c = inchar();
2425                         if (isspace(c)) {
2426                                 termch = c;
2427                                 break;
2428                         }
2429                         tmpstr[i] = c;
2430                 }
2431                 tmpstr[i++] = 0;
2432                 *vp = 0;
2433                 if (setjmp(bus_error_jmp) == 0) {
2434                         catch_memory_errors = 1;
2435                         sync();
2436                         *vp = kallsyms_lookup_name(tmpstr);
2437                         sync();
2438                 }
2439                 catch_memory_errors = 0;
2440                 if (!(*vp)) {
2441                         printf("unknown symbol '%s'\n", tmpstr);
2442                         return 0;
2443                 }
2444                 return 1;
2445         }
2446
2447         d = hexdigit(c);
2448         if (d == EOF) {
2449                 termch = c;
2450                 return 0;
2451         }
2452         v = 0;
2453         do {
2454                 v = (v << 4) + d;
2455                 c = inchar();
2456                 d = hexdigit(c);
2457         } while (d != EOF);
2458         termch = c;
2459         *vp = v;
2460         return 1;
2461 }
2462
2463 static void
2464 scannl(void)
2465 {
2466         int c;
2467
2468         c = termch;
2469         termch = 0;
2470         while( c != '\n' )
2471                 c = inchar();
2472 }
2473
2474 static int hexdigit(int c)
2475 {
2476         if( '0' <= c && c <= '9' )
2477                 return c - '0';
2478         if( 'A' <= c && c <= 'F' )
2479                 return c - ('A' - 10);
2480         if( 'a' <= c && c <= 'f' )
2481                 return c - ('a' - 10);
2482         return EOF;
2483 }
2484
2485 void
2486 getstring(char *s, int size)
2487 {
2488         int c;
2489
2490         c = skipbl();
2491         do {
2492                 if( size > 1 ){
2493                         *s++ = c;
2494                         --size;
2495                 }
2496                 c = inchar();
2497         } while( c != ' ' && c != '\t' && c != '\n' );
2498         termch = c;
2499         *s = 0;
2500 }
2501
2502 static char line[256];
2503 static char *lineptr;
2504
2505 static void
2506 flush_input(void)
2507 {
2508         lineptr = NULL;
2509 }
2510
2511 static int
2512 inchar(void)
2513 {
2514         if (lineptr == NULL || *lineptr == 0) {
2515                 if (xmon_gets(line, sizeof(line)) == NULL) {
2516                         lineptr = NULL;
2517                         return EOF;
2518                 }
2519                 lineptr = line;
2520         }
2521         return *lineptr++;
2522 }
2523
2524 static void
2525 take_input(char *str)
2526 {
2527         lineptr = str;
2528 }
2529
2530
2531 static void
2532 symbol_lookup(void)
2533 {
2534         int type = inchar();
2535         unsigned long addr;
2536         static char tmp[64];
2537
2538         switch (type) {
2539         case 'a':
2540                 if (scanhex(&addr))
2541                         xmon_print_symbol(addr, ": ", "\n");
2542                 termch = 0;
2543                 break;
2544         case 's':
2545                 getstring(tmp, 64);
2546                 if (setjmp(bus_error_jmp) == 0) {
2547                         catch_memory_errors = 1;
2548                         sync();
2549                         addr = kallsyms_lookup_name(tmp);
2550                         if (addr)
2551                                 printf("%s: %lx\n", tmp, addr);
2552                         else
2553                                 printf("Symbol '%s' not found.\n", tmp);
2554                         sync();
2555                 }
2556                 catch_memory_errors = 0;
2557                 termch = 0;
2558                 break;
2559         }
2560 }
2561
2562
2563 /* Print an address in numeric and symbolic form (if possible) */
2564 static void xmon_print_symbol(unsigned long address, const char *mid,
2565                               const char *after)
2566 {
2567         char *modname;
2568         const char *name = NULL;
2569         unsigned long offset, size;
2570
2571         printf(REG, address);
2572         if (setjmp(bus_error_jmp) == 0) {
2573                 catch_memory_errors = 1;
2574                 sync();
2575                 name = kallsyms_lookup(address, &size, &offset, &modname,
2576                                        tmpstr);
2577                 sync();
2578                 /* wait a little while to see if we get a machine check */
2579                 __delay(200);
2580         }
2581
2582         catch_memory_errors = 0;
2583
2584         if (name) {
2585                 printf("%s%s+%#lx/%#lx", mid, name, offset, size);
2586                 if (modname)
2587                         printf(" [%s]", modname);
2588         }
2589         printf("%s", after);
2590 }
2591
2592 #ifdef CONFIG_PPC_BOOK3S_64
2593 static void dump_slb(void)
2594 {
2595         int i;
2596         unsigned long esid,vsid,valid;
2597         unsigned long llp;
2598
2599         printf("SLB contents of cpu %x\n", smp_processor_id());
2600
2601         for (i = 0; i < mmu_slb_size; i++) {
2602                 asm volatile("slbmfee  %0,%1" : "=r" (esid) : "r" (i));
2603                 asm volatile("slbmfev  %0,%1" : "=r" (vsid) : "r" (i));
2604                 valid = (esid & SLB_ESID_V);
2605                 if (valid | esid | vsid) {
2606                         printf("%02d %016lx %016lx", i, esid, vsid);
2607                         if (valid) {
2608                                 llp = vsid & SLB_VSID_LLP;
2609                                 if (vsid & SLB_VSID_B_1T) {
2610                                         printf("  1T  ESID=%9lx  VSID=%13lx LLP:%3lx \n",
2611                                                 GET_ESID_1T(esid),
2612                                                 (vsid & ~SLB_VSID_B) >> SLB_VSID_SHIFT_1T,
2613                                                 llp);
2614                                 } else {
2615                                         printf(" 256M ESID=%9lx  VSID=%13lx LLP:%3lx \n",
2616                                                 GET_ESID(esid),
2617                                                 (vsid & ~SLB_VSID_B) >> SLB_VSID_SHIFT,
2618                                                 llp);
2619                                 }
2620                         } else
2621                                 printf("\n");
2622                 }
2623         }
2624 }
2625
2626 static void dump_stab(void)
2627 {
2628         int i;
2629         unsigned long *tmp = (unsigned long *)local_paca->stab_addr;
2630
2631         printf("Segment table contents of cpu %x\n", smp_processor_id());
2632
2633         for (i = 0; i < PAGE_SIZE/16; i++) {
2634                 unsigned long a, b;
2635
2636                 a = *tmp++;
2637                 b = *tmp++;
2638
2639                 if (a || b) {
2640                         printf("%03d %016lx ", i, a);
2641                         printf("%016lx\n", b);
2642                 }
2643         }
2644 }
2645
2646 void dump_segments(void)
2647 {
2648         if (mmu_has_feature(MMU_FTR_SLB))
2649                 dump_slb();
2650         else
2651                 dump_stab();
2652 }
2653 #endif
2654
2655 #ifdef CONFIG_PPC_STD_MMU_32
2656 void dump_segments(void)
2657 {
2658         int i;
2659
2660         printf("sr0-15 =");
2661         for (i = 0; i < 16; ++i)
2662                 printf(" %x", mfsrin(i));
2663         printf("\n");
2664 }
2665 #endif
2666
2667 #ifdef CONFIG_44x
2668 static void dump_tlb_44x(void)
2669 {
2670         int i;
2671
2672         for (i = 0; i < PPC44x_TLB_SIZE; i++) {
2673                 unsigned long w0,w1,w2;
2674                 asm volatile("tlbre  %0,%1,0" : "=r" (w0) : "r" (i));
2675                 asm volatile("tlbre  %0,%1,1" : "=r" (w1) : "r" (i));
2676                 asm volatile("tlbre  %0,%1,2" : "=r" (w2) : "r" (i));
2677                 printf("[%02x] %08x %08x %08x ", i, w0, w1, w2);
2678                 if (w0 & PPC44x_TLB_VALID) {
2679                         printf("V %08x -> %01x%08x %c%c%c%c%c",
2680                                w0 & PPC44x_TLB_EPN_MASK,
2681                                w1 & PPC44x_TLB_ERPN_MASK,
2682                                w1 & PPC44x_TLB_RPN_MASK,
2683                                (w2 & PPC44x_TLB_W) ? 'W' : 'w',
2684                                (w2 & PPC44x_TLB_I) ? 'I' : 'i',
2685                                (w2 & PPC44x_TLB_M) ? 'M' : 'm',
2686                                (w2 & PPC44x_TLB_G) ? 'G' : 'g',
2687                                (w2 & PPC44x_TLB_E) ? 'E' : 'e');
2688                 }
2689                 printf("\n");
2690         }
2691 }
2692 #endif /* CONFIG_44x */
2693
2694 #ifdef CONFIG_PPC_BOOK3E
2695 static void dump_tlb_book3e(void)
2696 {
2697         u32 mmucfg, pidmask, lpidmask;
2698         u64 ramask;
2699         int i, tlb, ntlbs, pidsz, lpidsz, rasz, lrat = 0;
2700         int mmu_version;
2701         static const char *pgsz_names[] = {
2702                 "  1K",
2703                 "  2K",
2704                 "  4K",
2705                 "  8K",
2706                 " 16K",
2707                 " 32K",
2708                 " 64K",
2709                 "128K",
2710                 "256K",
2711                 "512K",
2712                 "  1M",
2713                 "  2M",
2714                 "  4M",
2715                 "  8M",
2716                 " 16M",
2717                 " 32M",
2718                 " 64M",
2719                 "128M",
2720                 "256M",
2721                 "512M",
2722                 "  1G",
2723                 "  2G",
2724                 "  4G",
2725                 "  8G",
2726                 " 16G",
2727                 " 32G",
2728                 " 64G",
2729                 "128G",
2730                 "256G",
2731                 "512G",
2732                 "  1T",
2733                 "  2T",
2734         };
2735
2736         /* Gather some infos about the MMU */
2737         mmucfg = mfspr(SPRN_MMUCFG);
2738         mmu_version = (mmucfg & 3) + 1;
2739         ntlbs = ((mmucfg >> 2) & 3) + 1;
2740         pidsz = ((mmucfg >> 6) & 0x1f) + 1;
2741         lpidsz = (mmucfg >> 24) & 0xf;
2742         rasz = (mmucfg >> 16) & 0x7f;
2743         if ((mmu_version > 1) && (mmucfg & 0x10000))
2744                 lrat = 1;
2745         printf("Book3E MMU MAV=%d.0,%d TLBs,%d-bit PID,%d-bit LPID,%d-bit RA\n",
2746                mmu_version, ntlbs, pidsz, lpidsz, rasz);
2747         pidmask = (1ul << pidsz) - 1;
2748         lpidmask = (1ul << lpidsz) - 1;
2749         ramask = (1ull << rasz) - 1;
2750
2751         for (tlb = 0; tlb < ntlbs; tlb++) {
2752                 u32 tlbcfg;
2753                 int nent, assoc, new_cc = 1;
2754                 printf("TLB %d:\n------\n", tlb);
2755                 switch(tlb) {
2756                 case 0:
2757                         tlbcfg = mfspr(SPRN_TLB0CFG);
2758                         break;
2759                 case 1:
2760                         tlbcfg = mfspr(SPRN_TLB1CFG);
2761                         break;
2762                 case 2:
2763                         tlbcfg = mfspr(SPRN_TLB2CFG);
2764                         break;
2765                 case 3:
2766                         tlbcfg = mfspr(SPRN_TLB3CFG);
2767                         break;
2768                 default:
2769                         printf("Unsupported TLB number !\n");
2770                         continue;
2771                 }
2772                 nent = tlbcfg & 0xfff;
2773                 assoc = (tlbcfg >> 24) & 0xff;
2774                 for (i = 0; i < nent; i++) {
2775                         u32 mas0 = MAS0_TLBSEL(tlb);
2776                         u32 mas1 = MAS1_TSIZE(BOOK3E_PAGESZ_4K);
2777                         u64 mas2 = 0;
2778                         u64 mas7_mas3;
2779                         int esel = i, cc = i;
2780
2781                         if (assoc != 0) {
2782                                 cc = i / assoc;
2783                                 esel = i % assoc;
2784                                 mas2 = cc * 0x1000;
2785                         }
2786
2787                         mas0 |= MAS0_ESEL(esel);
2788                         mtspr(SPRN_MAS0, mas0);
2789                         mtspr(SPRN_MAS1, mas1);
2790                         mtspr(SPRN_MAS2, mas2);
2791                         asm volatile("tlbre  0,0,0" : : : "memory");
2792                         mas1 = mfspr(SPRN_MAS1);
2793                         mas2 = mfspr(SPRN_MAS2);
2794                         mas7_mas3 = mfspr(SPRN_MAS7_MAS3);
2795                         if (assoc && (i % assoc) == 0)
2796                                 new_cc = 1;
2797                         if (!(mas1 & MAS1_VALID))
2798                                 continue;
2799                         if (assoc == 0)
2800                                 printf("%04x- ", i);
2801                         else if (new_cc)
2802                                 printf("%04x-%c", cc, 'A' + esel);
2803                         else
2804                                 printf("    |%c", 'A' + esel);
2805                         new_cc = 0;
2806                         printf(" %016llx %04x %s %c%c AS%c",
2807                                mas2 & ~0x3ffull,
2808                                (mas1 >> 16) & 0x3fff,
2809                                pgsz_names[(mas1 >> 7) & 0x1f],
2810                                mas1 & MAS1_IND ? 'I' : ' ',
2811                                mas1 & MAS1_IPROT ? 'P' : ' ',
2812                                mas1 & MAS1_TS ? '1' : '0');
2813                         printf(" %c%c%c%c%c%c%c",
2814                                mas2 & MAS2_X0 ? 'a' : ' ',
2815                                mas2 & MAS2_X1 ? 'v' : ' ',
2816                                mas2 & MAS2_W  ? 'w' : ' ',
2817                                mas2 & MAS2_I  ? 'i' : ' ',
2818                                mas2 & MAS2_M  ? 'm' : ' ',
2819                                mas2 & MAS2_G  ? 'g' : ' ',
2820                                mas2 & MAS2_E  ? 'e' : ' ');
2821                         printf(" %016llx", mas7_mas3 & ramask & ~0x7ffull);
2822                         if (mas1 & MAS1_IND)
2823                                 printf(" %s\n",
2824                                        pgsz_names[(mas7_mas3 >> 1) & 0x1f]);
2825                         else
2826                                 printf(" U%c%c%c S%c%c%c\n",
2827                                        mas7_mas3 & MAS3_UX ? 'x' : ' ',
2828                                        mas7_mas3 & MAS3_UW ? 'w' : ' ',
2829                                        mas7_mas3 & MAS3_UR ? 'r' : ' ',
2830                                        mas7_mas3 & MAS3_SX ? 'x' : ' ',
2831                                        mas7_mas3 & MAS3_SW ? 'w' : ' ',
2832                                        mas7_mas3 & MAS3_SR ? 'r' : ' ');
2833                 }
2834         }
2835 }
2836 #endif /* CONFIG_PPC_BOOK3E */
2837
2838 static void xmon_init(int enable)
2839 {
2840         if (enable) {
2841                 __debugger = xmon;
2842                 __debugger_ipi = xmon_ipi;
2843                 __debugger_bpt = xmon_bpt;
2844                 __debugger_sstep = xmon_sstep;
2845                 __debugger_iabr_match = xmon_iabr_match;
2846                 __debugger_dabr_match = xmon_dabr_match;
2847                 __debugger_fault_handler = xmon_fault_handler;
2848         } else {
2849                 __debugger = NULL;
2850                 __debugger_ipi = NULL;
2851                 __debugger_bpt = NULL;
2852                 __debugger_sstep = NULL;
2853                 __debugger_iabr_match = NULL;
2854                 __debugger_dabr_match = NULL;
2855                 __debugger_fault_handler = NULL;
2856         }
2857         xmon_map_scc();
2858 }
2859
2860 #ifdef CONFIG_MAGIC_SYSRQ
2861 static void sysrq_handle_xmon(int key)
2862 {
2863         /* ensure xmon is enabled */
2864         xmon_init(1);
2865         debugger(get_irq_regs());
2866 }
2867
2868 static struct sysrq_key_op sysrq_xmon_op = {
2869         .handler =      sysrq_handle_xmon,
2870         .help_msg =     "Xmon",
2871         .action_msg =   "Entering xmon",
2872 };
2873
2874 static int __init setup_xmon_sysrq(void)
2875 {
2876         register_sysrq_key('x', &sysrq_xmon_op);
2877         return 0;
2878 }
2879 __initcall(setup_xmon_sysrq);
2880 #endif /* CONFIG_MAGIC_SYSRQ */
2881
2882 static int __initdata xmon_early, xmon_off;
2883
2884 static int __init early_parse_xmon(char *p)
2885 {
2886         if (!p || strncmp(p, "early", 5) == 0) {
2887                 /* just "xmon" is equivalent to "xmon=early" */
2888                 xmon_init(1);
2889                 xmon_early = 1;
2890         } else if (strncmp(p, "on", 2) == 0)
2891                 xmon_init(1);
2892         else if (strncmp(p, "off", 3) == 0)
2893                 xmon_off = 1;
2894         else if (strncmp(p, "nobt", 4) == 0)
2895                 xmon_no_auto_backtrace = 1;
2896         else
2897                 return 1;
2898
2899         return 0;
2900 }
2901 early_param("xmon", early_parse_xmon);
2902
2903 void __init xmon_setup(void)
2904 {
2905 #ifdef CONFIG_XMON_DEFAULT
2906         if (!xmon_off)
2907                 xmon_init(1);
2908 #endif
2909         if (xmon_early)
2910                 debugger(NULL);
2911 }
2912
2913 #ifdef CONFIG_SPU_BASE
2914
2915 struct spu_info {
2916         struct spu *spu;
2917         u64 saved_mfc_sr1_RW;
2918         u32 saved_spu_runcntl_RW;
2919         unsigned long dump_addr;
2920         u8 stopped_ok;
2921 };
2922
2923 #define XMON_NUM_SPUS   16      /* Enough for current hardware */
2924
2925 static struct spu_info spu_info[XMON_NUM_SPUS];
2926
2927 void xmon_register_spus(struct list_head *list)
2928 {
2929         struct spu *spu;
2930
2931         list_for_each_entry(spu, list, full_list) {
2932                 if (spu->number >= XMON_NUM_SPUS) {
2933                         WARN_ON(1);
2934                         continue;
2935                 }
2936
2937                 spu_info[spu->number].spu = spu;
2938                 spu_info[spu->number].stopped_ok = 0;
2939                 spu_info[spu->number].dump_addr = (unsigned long)
2940                                 spu_info[spu->number].spu->local_store;
2941         }
2942 }
2943
2944 static void stop_spus(void)
2945 {
2946         struct spu *spu;
2947         int i;
2948         u64 tmp;
2949
2950         for (i = 0; i < XMON_NUM_SPUS; i++) {
2951                 if (!spu_info[i].spu)
2952                         continue;
2953
2954                 if (setjmp(bus_error_jmp) == 0) {
2955                         catch_memory_errors = 1;
2956                         sync();
2957
2958                         spu = spu_info[i].spu;
2959
2960                         spu_info[i].saved_spu_runcntl_RW =
2961                                 in_be32(&spu->problem->spu_runcntl_RW);
2962
2963                         tmp = spu_mfc_sr1_get(spu);
2964                         spu_info[i].saved_mfc_sr1_RW = tmp;
2965
2966                         tmp &= ~MFC_STATE1_MASTER_RUN_CONTROL_MASK;
2967                         spu_mfc_sr1_set(spu, tmp);
2968
2969                         sync();
2970                         __delay(200);
2971
2972                         spu_info[i].stopped_ok = 1;
2973
2974                         printf("Stopped spu %.2d (was %s)\n", i,
2975                                         spu_info[i].saved_spu_runcntl_RW ?
2976                                         "running" : "stopped");
2977                 } else {
2978                         catch_memory_errors = 0;
2979                         printf("*** Error stopping spu %.2d\n", i);
2980                 }
2981                 catch_memory_errors = 0;
2982         }
2983 }
2984
2985 static void restart_spus(void)
2986 {
2987         struct spu *spu;
2988         int i;
2989
2990         for (i = 0; i < XMON_NUM_SPUS; i++) {
2991                 if (!spu_info[i].spu)
2992                         continue;
2993
2994                 if (!spu_info[i].stopped_ok) {
2995                         printf("*** Error, spu %d was not successfully stopped"
2996                                         ", not restarting\n", i);
2997                         continue;
2998                 }
2999
3000                 if (setjmp(bus_error_jmp) == 0) {
3001                         catch_memory_errors = 1;
3002                         sync();
3003
3004                         spu = spu_info[i].spu;
3005                         spu_mfc_sr1_set(spu, spu_info[i].saved_mfc_sr1_RW);
3006                         out_be32(&spu->problem->spu_runcntl_RW,
3007                                         spu_info[i].saved_spu_runcntl_RW);
3008
3009                         sync();
3010                         __delay(200);
3011
3012                         printf("Restarted spu %.2d\n", i);
3013                 } else {
3014                         catch_memory_errors = 0;
3015                         printf("*** Error restarting spu %.2d\n", i);
3016                 }
3017                 catch_memory_errors = 0;
3018         }
3019 }
3020
3021 #define DUMP_WIDTH      23
3022 #define DUMP_VALUE(format, field, value)                                \
3023 do {                                                                    \
3024         if (setjmp(bus_error_jmp) == 0) {                               \
3025                 catch_memory_errors = 1;                                \
3026                 sync();                                                 \
3027                 printf("  %-*s = "format"\n", DUMP_WIDTH,               \
3028                                 #field, value);                         \
3029                 sync();                                                 \
3030                 __delay(200);                                           \
3031         } else {                                                        \
3032                 catch_memory_errors = 0;                                \
3033                 printf("  %-*s = *** Error reading field.\n",           \
3034                                         DUMP_WIDTH, #field);            \
3035         }                                                               \
3036         catch_memory_errors = 0;                                        \
3037 } while (0)
3038
3039 #define DUMP_FIELD(obj, format, field)  \
3040         DUMP_VALUE(format, field, obj->field)
3041
3042 static void dump_spu_fields(struct spu *spu)
3043 {
3044         printf("Dumping spu fields at address %p:\n", spu);
3045
3046         DUMP_FIELD(spu, "0x%x", number);
3047         DUMP_FIELD(spu, "%s", name);
3048         DUMP_FIELD(spu, "0x%lx", local_store_phys);
3049         DUMP_FIELD(spu, "0x%p", local_store);
3050         DUMP_FIELD(spu, "0x%lx", ls_size);
3051         DUMP_FIELD(spu, "0x%x", node);
3052         DUMP_FIELD(spu, "0x%lx", flags);
3053         DUMP_FIELD(spu, "%d", class_0_pending);
3054         DUMP_FIELD(spu, "0x%lx", class_0_dar);
3055         DUMP_FIELD(spu, "0x%lx", class_1_dar);
3056         DUMP_FIELD(spu, "0x%lx", class_1_dsisr);
3057         DUMP_FIELD(spu, "0x%lx", irqs[0]);
3058         DUMP_FIELD(spu, "0x%lx", irqs[1]);
3059         DUMP_FIELD(spu, "0x%lx", irqs[2]);
3060         DUMP_FIELD(spu, "0x%x", slb_replace);
3061         DUMP_FIELD(spu, "%d", pid);
3062         DUMP_FIELD(spu, "0x%p", mm);
3063         DUMP_FIELD(spu, "0x%p", ctx);
3064         DUMP_FIELD(spu, "0x%p", rq);
3065         DUMP_FIELD(spu, "0x%p", timestamp);
3066         DUMP_FIELD(spu, "0x%lx", problem_phys);
3067         DUMP_FIELD(spu, "0x%p", problem);
3068         DUMP_VALUE("0x%x", problem->spu_runcntl_RW,
3069                         in_be32(&spu->problem->spu_runcntl_RW));
3070         DUMP_VALUE("0x%x", problem->spu_status_R,
3071                         in_be32(&spu->problem->spu_status_R));
3072         DUMP_VALUE("0x%x", problem->spu_npc_RW,
3073                         in_be32(&spu->problem->spu_npc_RW));
3074         DUMP_FIELD(spu, "0x%p", priv2);
3075         DUMP_FIELD(spu, "0x%p", pdata);
3076 }
3077
3078 int
3079 spu_inst_dump(unsigned long adr, long count, int praddr)
3080 {
3081         return generic_inst_dump(adr, count, praddr, print_insn_spu);
3082 }
3083
3084 static void dump_spu_ls(unsigned long num, int subcmd)
3085 {
3086         unsigned long offset, addr, ls_addr;
3087
3088         if (setjmp(bus_error_jmp) == 0) {
3089                 catch_memory_errors = 1;
3090                 sync();
3091                 ls_addr = (unsigned long)spu_info[num].spu->local_store;
3092                 sync();
3093                 __delay(200);
3094         } else {
3095                 catch_memory_errors = 0;
3096                 printf("*** Error: accessing spu info for spu %d\n", num);
3097                 return;
3098         }
3099         catch_memory_errors = 0;
3100
3101         if (scanhex(&offset))
3102                 addr = ls_addr + offset;
3103         else
3104                 addr = spu_info[num].dump_addr;
3105
3106         if (addr >= ls_addr + LS_SIZE) {
3107                 printf("*** Error: address outside of local store\n");
3108                 return;
3109         }
3110
3111         switch (subcmd) {
3112         case 'i':
3113                 addr += spu_inst_dump(addr, 16, 1);
3114                 last_cmd = "sdi\n";
3115                 break;
3116         default:
3117                 prdump(addr, 64);
3118                 addr += 64;
3119                 last_cmd = "sd\n";
3120                 break;
3121         }
3122
3123         spu_info[num].dump_addr = addr;
3124 }
3125
3126 static int do_spu_cmd(void)
3127 {
3128         static unsigned long num = 0;
3129         int cmd, subcmd = 0;
3130
3131         cmd = inchar();
3132         switch (cmd) {
3133         case 's':
3134                 stop_spus();
3135                 break;
3136         case 'r':
3137                 restart_spus();
3138                 break;
3139         case 'd':
3140                 subcmd = inchar();
3141                 if (isxdigit(subcmd) || subcmd == '\n')
3142                         termch = subcmd;
3143         case 'f':
3144                 scanhex(&num);
3145                 if (num >= XMON_NUM_SPUS || !spu_info[num].spu) {
3146                         printf("*** Error: invalid spu number\n");
3147                         return 0;
3148                 }
3149
3150                 switch (cmd) {
3151                 case 'f':
3152                         dump_spu_fields(spu_info[num].spu);
3153                         break;
3154                 default:
3155                         dump_spu_ls(num, subcmd);
3156                         break;
3157                 }
3158
3159                 break;
3160         default:
3161                 return -1;
3162         }
3163
3164         return 0;
3165 }
3166 #else /* ! CONFIG_SPU_BASE */
3167 static int do_spu_cmd(void)
3168 {
3169         return -1;
3170 }
3171 #endif