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