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