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