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