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