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