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