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