powerpc: 32-bit fixes for xmon
[linux-2.6.git] / arch / powerpc / xmon / xmon.c
1 /*
2  * Routines providing a simple monitor for use on the PowerMac.
3  *
4  * Copyright (C) 1996-2005 Paul Mackerras.
5  *
6  *      This program is free software; you can redistribute it and/or
7  *      modify it under the terms of the GNU General Public License
8  *      as published by the Free Software Foundation; either version
9  *      2 of the License, or (at your option) any later version.
10  */
11 #include <linux/config.h>
12 #include <linux/errno.h>
13 #include <linux/sched.h>
14 #include <linux/smp.h>
15 #include <linux/mm.h>
16 #include <linux/reboot.h>
17 #include <linux/delay.h>
18 #include <linux/kallsyms.h>
19 #include <linux/cpumask.h>
20 #include <linux/module.h>
21 #include <linux/sysrq.h>
22
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 #ifdef CONFIG_PMAC_BACKLIGHT
29 #include <asm/backlight.h>
30 #endif
31 #include <asm/processor.h>
32 #include <asm/pgtable.h>
33 #include <asm/mmu.h>
34 #include <asm/mmu_context.h>
35 #include <asm/cputable.h>
36 #include <asm/rtas.h>
37 #include <asm/sstep.h>
38 #include <asm/bug.h>
39
40 #ifdef CONFIG_PPC64
41 #include <asm/hvcall.h>
42 #include <asm/paca.h>
43 #endif
44
45 #include "nonstdio.h"
46
47 #define scanhex xmon_scanhex
48 #define skipbl  xmon_skipbl
49
50 #ifdef CONFIG_SMP
51 cpumask_t cpus_in_xmon = CPU_MASK_NONE;
52 static unsigned long xmon_taken = 1;
53 static int xmon_owner;
54 static int xmon_gate;
55 #endif /* CONFIG_SMP */
56
57 static unsigned long in_xmon = 0;
58
59 static unsigned long adrs;
60 static int size = 1;
61 #define MAX_DUMP (128 * 1024)
62 static unsigned long ndump = 64;
63 static unsigned long nidump = 16;
64 static unsigned long ncsum = 4096;
65 static int termch;
66 static char tmpstr[128];
67
68 #define JMP_BUF_LEN     23
69 static long bus_error_jmp[JMP_BUF_LEN];
70 static int catch_memory_errors;
71 static long *xmon_fault_jmp[NR_CPUS];
72 #define setjmp xmon_setjmp
73 #define longjmp xmon_longjmp
74
75 /* Breakpoint stuff */
76 struct bpt {
77         unsigned long   address;
78         unsigned int    instr[2];
79         atomic_t        ref_count;
80         int             enabled;
81         unsigned long   pad;
82 };
83
84 /* Bits in bpt.enabled */
85 #define BP_IABR_TE      1               /* IABR translation enabled */
86 #define BP_IABR         2
87 #define BP_TRAP         8
88 #define BP_DABR         0x10
89
90 #define NBPTS   256
91 static struct bpt bpts[NBPTS];
92 static struct bpt dabr;
93 static struct bpt *iabr;
94 static unsigned bpinstr = 0x7fe00008;   /* trap */
95
96 #define BP_NUM(bp)      ((bp) - bpts + 1)
97
98 /* Prototypes */
99 static int cmds(struct pt_regs *);
100 static int mread(unsigned long, void *, int);
101 static int mwrite(unsigned long, void *, int);
102 static int handle_fault(struct pt_regs *);
103 static void byterev(unsigned char *, int);
104 static void memex(void);
105 static int bsesc(void);
106 static void dump(void);
107 static void prdump(unsigned long, long);
108 static int ppc_inst_dump(unsigned long, long, int);
109 void print_address(unsigned long);
110 static void backtrace(struct pt_regs *);
111 static void excprint(struct pt_regs *);
112 static void prregs(struct pt_regs *);
113 static void memops(int);
114 static void memlocate(void);
115 static void memzcan(void);
116 static void memdiffs(unsigned char *, unsigned char *, unsigned, unsigned);
117 int skipbl(void);
118 int scanhex(unsigned long *valp);
119 static void scannl(void);
120 static int hexdigit(int);
121 void getstring(char *, int);
122 static void flush_input(void);
123 static int inchar(void);
124 static void take_input(char *);
125 static unsigned long read_spr(int);
126 static void write_spr(int, unsigned long);
127 static void super_regs(void);
128 static void remove_bpts(void);
129 static void insert_bpts(void);
130 static void remove_cpu_bpts(void);
131 static void insert_cpu_bpts(void);
132 static struct bpt *at_breakpoint(unsigned long pc);
133 static struct bpt *in_breakpoint_table(unsigned long pc, unsigned long *offp);
134 static int  do_step(struct pt_regs *);
135 static void bpt_cmds(void);
136 static void cacheflush(void);
137 static int  cpu_cmd(void);
138 static void csum(void);
139 static void bootcmds(void);
140 static void proccall(void);
141 void dump_segments(void);
142 static void symbol_lookup(void);
143 static void xmon_print_symbol(unsigned long address, const char *mid,
144                               const char *after);
145 static const char *getvecname(unsigned long vec);
146
147 extern int print_insn_powerpc(unsigned long, unsigned long, int);
148
149 extern void xmon_enter(void);
150 extern void xmon_leave(void);
151
152 extern long setjmp(long *);
153 extern void longjmp(long *, long);
154 extern void xmon_save_regs(struct pt_regs *);
155
156 #ifdef CONFIG_PPC64
157 #define REG             "%.16lx"
158 #define REGS_PER_LINE   4
159 #define LAST_VOLATILE   13
160 #else
161 #define REG             "%.8lx"
162 #define REGS_PER_LINE   8
163 #define LAST_VOLATILE   12
164 #endif
165
166 #define GETWORD(v)      (((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
167
168 #define isxdigit(c)     (('0' <= (c) && (c) <= '9') \
169                          || ('a' <= (c) && (c) <= 'f') \
170                          || ('A' <= (c) && (c) <= 'F'))
171 #define isalnum(c)      (('0' <= (c) && (c) <= '9') \
172                          || ('a' <= (c) && (c) <= 'z') \
173                          || ('A' <= (c) && (c) <= 'Z'))
174 #define isspace(c)      (c == ' ' || c == '\t' || c == 10 || c == 13 || c == 0)
175
176 static char *help_string = "\
177 Commands:\n\
178   b     show breakpoints\n\
179   bd    set data breakpoint\n\
180   bi    set instruction breakpoint\n\
181   bc    clear breakpoint\n"
182 #ifdef CONFIG_SMP
183   "\
184   c     print cpus stopped in xmon\n\
185   c#    try to switch to cpu number h (in hex)\n"
186 #endif
187   "\
188   C     checksum\n\
189   d     dump bytes\n\
190   di    dump instructions\n\
191   df    dump float values\n\
192   dd    dump double values\n\
193   e     print exception information\n\
194   f     flush cache\n\
195   la    lookup symbol+offset of specified address\n\
196   ls    lookup address of specified symbol\n\
197   m     examine/change memory\n\
198   mm    move a block of memory\n\
199   ms    set a block of memory\n\
200   md    compare two blocks of memory\n\
201   ml    locate a block of memory\n\
202   mz    zero a block of memory\n\
203   mi    show information about memory allocation\n\
204   p     call a procedure\n\
205   r     print registers\n\
206   s     single step\n\
207   S     print special registers\n\
208   t     print backtrace\n\
209   x     exit monitor and recover\n\
210   X     exit monitor and dont recover\n"
211 #ifdef CONFIG_PPC64
212 "  u    dump segment table or SLB\n"
213 #endif
214 #ifdef CONFIG_PPC_STD_MMU_32
215 "  u    dump segment registers\n"
216 #endif
217 "  ?    help\n"
218 "  zr   reboot\n\
219   zh    halt\n"
220 ;
221
222 static struct pt_regs *xmon_regs;
223
224 static inline void sync(void)
225 {
226         asm volatile("sync; isync");
227 }
228
229 static inline void store_inst(void *p)
230 {
231         asm volatile ("dcbst 0,%0; sync; icbi 0,%0; isync" : : "r" (p));
232 }
233
234 static inline void cflush(void *p)
235 {
236         asm volatile ("dcbf 0,%0; icbi 0,%0" : : "r" (p));
237 }
238
239 static inline void cinval(void *p)
240 {
241         asm volatile ("dcbi 0,%0; icbi 0,%0" : : "r" (p));
242 }
243
244 /*
245  * Disable surveillance (the service processor watchdog function)
246  * while we are in xmon.
247  * XXX we should re-enable it when we leave. :)
248  */
249 #define SURVEILLANCE_TOKEN      9000
250
251 static inline void disable_surveillance(void)
252 {
253 #ifdef CONFIG_PPC_PSERIES
254         /* Since this can't be a module, args should end up below 4GB. */
255         static struct rtas_args args;
256
257         /*
258          * At this point we have got all the cpus we can into
259          * xmon, so there is hopefully no other cpu calling RTAS
260          * at the moment, even though we don't take rtas.lock.
261          * If we did try to take rtas.lock there would be a
262          * real possibility of deadlock.
263          */
264         args.token = rtas_token("set-indicator");
265         if (args.token == RTAS_UNKNOWN_SERVICE)
266                 return;
267         args.nargs = 3;
268         args.nret = 1;
269         args.rets = &args.args[3];
270         args.args[0] = SURVEILLANCE_TOKEN;
271         args.args[1] = 0;
272         args.args[2] = 0;
273         enter_rtas(__pa(&args));
274 #endif /* CONFIG_PPC_PSERIES */
275 }
276
277 #ifdef CONFIG_SMP
278 static int xmon_speaker;
279
280 static void get_output_lock(void)
281 {
282         int me = smp_processor_id() + 0x100;
283         int last_speaker = 0, prev;
284         long timeout;
285
286         if (xmon_speaker == me)
287                 return;
288         for (;;) {
289                 if (xmon_speaker == 0) {
290                         last_speaker = cmpxchg(&xmon_speaker, 0, me);
291                         if (last_speaker == 0)
292                                 return;
293                 }
294                 timeout = 10000000;
295                 while (xmon_speaker == last_speaker) {
296                         if (--timeout > 0)
297                                 continue;
298                         /* hostile takeover */
299                         prev = cmpxchg(&xmon_speaker, last_speaker, me);
300                         if (prev == last_speaker)
301                                 return;
302                         break;
303                 }
304         }
305 }
306
307 static void release_output_lock(void)
308 {
309         xmon_speaker = 0;
310 }
311 #endif
312
313 int xmon_core(struct pt_regs *regs, int fromipi)
314 {
315         int cmd = 0;
316         unsigned long msr;
317         struct bpt *bp;
318         long recurse_jmp[JMP_BUF_LEN];
319         unsigned long offset;
320 #ifdef CONFIG_SMP
321         int cpu;
322         int secondary;
323         unsigned long timeout;
324 #endif
325
326         msr = mfmsr();
327         mtmsr(msr & ~MSR_EE);   /* disable interrupts */
328
329         bp = in_breakpoint_table(regs->nip, &offset);
330         if (bp != NULL) {
331                 regs->nip = bp->address + offset;
332                 atomic_dec(&bp->ref_count);
333         }
334
335         remove_cpu_bpts();
336
337 #ifdef CONFIG_SMP
338         cpu = smp_processor_id();
339         if (cpu_isset(cpu, cpus_in_xmon)) {
340                 get_output_lock();
341                 excprint(regs);
342                 printf("cpu 0x%x: Exception %lx %s in xmon, "
343                        "returning to main loop\n",
344                        cpu, regs->trap, getvecname(TRAP(regs)));
345                 release_output_lock();
346                 longjmp(xmon_fault_jmp[cpu], 1);
347         }
348
349         if (setjmp(recurse_jmp) != 0) {
350                 if (!in_xmon || !xmon_gate) {
351                         get_output_lock();
352                         printf("xmon: WARNING: bad recursive fault "
353                                "on cpu 0x%x\n", cpu);
354                         release_output_lock();
355                         goto waiting;
356                 }
357                 secondary = !(xmon_taken && cpu == xmon_owner);
358                 goto cmdloop;
359         }
360
361         xmon_fault_jmp[cpu] = recurse_jmp;
362         cpu_set(cpu, cpus_in_xmon);
363
364         bp = NULL;
365         if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) == (MSR_IR|MSR_SF))
366                 bp = at_breakpoint(regs->nip);
367         if (bp || (regs->msr & MSR_RI) == 0)
368                 fromipi = 0;
369
370         if (!fromipi) {
371                 get_output_lock();
372                 excprint(regs);
373                 if (bp) {
374                         printf("cpu 0x%x stopped at breakpoint 0x%x (",
375                                cpu, BP_NUM(bp));
376                         xmon_print_symbol(regs->nip, " ", ")\n");
377                 }
378                 if ((regs->msr & MSR_RI) == 0)
379                         printf("WARNING: exception is not recoverable, "
380                                "can't continue\n");
381                 release_output_lock();
382         }
383
384  waiting:
385         secondary = 1;
386         while (secondary && !xmon_gate) {
387                 if (in_xmon == 0) {
388                         if (fromipi)
389                                 goto leave;
390                         secondary = test_and_set_bit(0, &in_xmon);
391                 }
392                 barrier();
393         }
394
395         if (!secondary && !xmon_gate) {
396                 /* we are the first cpu to come in */
397                 /* interrupt other cpu(s) */
398                 int ncpus = num_online_cpus();
399
400                 xmon_owner = cpu;
401                 mb();
402                 if (ncpus > 1) {
403                         smp_send_debugger_break(MSG_ALL_BUT_SELF);
404                         /* wait for other cpus to come in */
405                         for (timeout = 100000000; timeout != 0; --timeout) {
406                                 if (cpus_weight(cpus_in_xmon) >= ncpus)
407                                         break;
408                                 barrier();
409                         }
410                 }
411                 remove_bpts();
412                 disable_surveillance();
413                 /* for breakpoint or single step, print the current instr. */
414                 if (bp || TRAP(regs) == 0xd00)
415                         ppc_inst_dump(regs->nip, 1, 0);
416                 printf("enter ? for help\n");
417                 mb();
418                 xmon_gate = 1;
419                 barrier();
420         }
421
422  cmdloop:
423         while (in_xmon) {
424                 if (secondary) {
425                         if (cpu == xmon_owner) {
426                                 if (!test_and_set_bit(0, &xmon_taken)) {
427                                         secondary = 0;
428                                         continue;
429                                 }
430                                 /* missed it */
431                                 while (cpu == xmon_owner)
432                                         barrier();
433                         }
434                         barrier();
435                 } else {
436                         cmd = cmds(regs);
437                         if (cmd != 0) {
438                                 /* exiting xmon */
439                                 insert_bpts();
440                                 xmon_gate = 0;
441                                 wmb();
442                                 in_xmon = 0;
443                                 break;
444                         }
445                         /* have switched to some other cpu */
446                         secondary = 1;
447                 }
448         }
449  leave:
450         cpu_clear(cpu, cpus_in_xmon);
451         xmon_fault_jmp[cpu] = NULL;
452
453 #else
454         /* UP is simple... */
455         if (in_xmon) {
456                 printf("Exception %lx %s in xmon, returning to main loop\n",
457                        regs->trap, getvecname(TRAP(regs)));
458                 longjmp(xmon_fault_jmp[0], 1);
459         }
460         if (setjmp(recurse_jmp) == 0) {
461                 xmon_fault_jmp[0] = recurse_jmp;
462                 in_xmon = 1;
463
464                 excprint(regs);
465                 bp = at_breakpoint(regs->nip);
466                 if (bp) {
467                         printf("Stopped at breakpoint %x (", BP_NUM(bp));
468                         xmon_print_symbol(regs->nip, " ", ")\n");
469                 }
470                 if ((regs->msr & MSR_RI) == 0)
471                         printf("WARNING: exception is not recoverable, "
472                                "can't continue\n");
473                 remove_bpts();
474                 disable_surveillance();
475                 /* for breakpoint or single step, print the current instr. */
476                 if (bp || TRAP(regs) == 0xd00)
477                         ppc_inst_dump(regs->nip, 1, 0);
478                 printf("enter ? for help\n");
479         }
480
481         cmd = cmds(regs);
482
483         insert_bpts();
484         in_xmon = 0;
485 #endif
486
487         if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) == (MSR_IR|MSR_SF)) {
488                 bp = at_breakpoint(regs->nip);
489                 if (bp != NULL) {
490                         int stepped = emulate_step(regs, bp->instr[0]);
491                         if (stepped == 0) {
492                                 regs->nip = (unsigned long) &bp->instr[0];
493                                 atomic_inc(&bp->ref_count);
494                         } else if (stepped < 0) {
495                                 printf("Couldn't single-step %s instruction\n",
496                                     (IS_RFID(bp->instr[0])? "rfid": "mtmsrd"));
497                         }
498                 }
499         }
500
501         insert_cpu_bpts();
502
503         mtmsr(msr);             /* restore interrupt enable */
504
505         return cmd != 'X';
506 }
507
508 int xmon(struct pt_regs *excp)
509 {
510         struct pt_regs regs;
511
512         if (excp == NULL) {
513                 xmon_save_regs(&regs);
514                 excp = &regs;
515         }
516         return xmon_core(excp, 0);
517 }
518 EXPORT_SYMBOL(xmon);
519
520 irqreturn_t
521 xmon_irq(int irq, void *d, struct pt_regs *regs)
522 {
523         unsigned long flags;
524         local_irq_save(flags);
525         printf("Keyboard interrupt\n");
526         xmon(regs);
527         local_irq_restore(flags);
528         return IRQ_HANDLED;
529 }
530
531 int xmon_bpt(struct pt_regs *regs)
532 {
533         struct bpt *bp;
534         unsigned long offset;
535
536         if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF))
537                 return 0;
538
539         /* Are we at the trap at bp->instr[1] for some bp? */
540         bp = in_breakpoint_table(regs->nip, &offset);
541         if (bp != NULL && offset == 4) {
542                 regs->nip = bp->address + 4;
543                 atomic_dec(&bp->ref_count);
544                 return 1;
545         }
546
547         /* Are we at a breakpoint? */
548         bp = at_breakpoint(regs->nip);
549         if (!bp)
550                 return 0;
551
552         xmon_core(regs, 0);
553
554         return 1;
555 }
556
557 int xmon_sstep(struct pt_regs *regs)
558 {
559         if (user_mode(regs))
560                 return 0;
561         xmon_core(regs, 0);
562         return 1;
563 }
564
565 int xmon_dabr_match(struct pt_regs *regs)
566 {
567         if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF))
568                 return 0;
569         if (dabr.enabled == 0)
570                 return 0;
571         xmon_core(regs, 0);
572         return 1;
573 }
574
575 int xmon_iabr_match(struct pt_regs *regs)
576 {
577         if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF))
578                 return 0;
579         if (iabr == 0)
580                 return 0;
581         xmon_core(regs, 0);
582         return 1;
583 }
584
585 int xmon_ipi(struct pt_regs *regs)
586 {
587 #ifdef CONFIG_SMP
588         if (in_xmon && !cpu_isset(smp_processor_id(), cpus_in_xmon))
589                 xmon_core(regs, 1);
590 #endif
591         return 0;
592 }
593
594 int xmon_fault_handler(struct pt_regs *regs)
595 {
596         struct bpt *bp;
597         unsigned long offset;
598
599         if (in_xmon && catch_memory_errors)
600                 handle_fault(regs);     /* doesn't return */
601
602         if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) == (MSR_IR|MSR_SF)) {
603                 bp = in_breakpoint_table(regs->nip, &offset);
604                 if (bp != NULL) {
605                         regs->nip = bp->address + offset;
606                         atomic_dec(&bp->ref_count);
607                 }
608         }
609
610         return 0;
611 }
612
613 static struct bpt *at_breakpoint(unsigned long pc)
614 {
615         int i;
616         struct bpt *bp;
617
618         bp = bpts;
619         for (i = 0; i < NBPTS; ++i, ++bp)
620                 if (bp->enabled && pc == bp->address)
621                         return bp;
622         return NULL;
623 }
624
625 static struct bpt *in_breakpoint_table(unsigned long nip, unsigned long *offp)
626 {
627         unsigned long off;
628
629         off = nip - (unsigned long) bpts;
630         if (off >= sizeof(bpts))
631                 return NULL;
632         off %= sizeof(struct bpt);
633         if (off != offsetof(struct bpt, instr[0])
634             && off != offsetof(struct bpt, instr[1]))
635                 return NULL;
636         *offp = off - offsetof(struct bpt, instr[0]);
637         return (struct bpt *) (nip - off);
638 }
639
640 static struct bpt *new_breakpoint(unsigned long a)
641 {
642         struct bpt *bp;
643
644         a &= ~3UL;
645         bp = at_breakpoint(a);
646         if (bp)
647                 return bp;
648
649         for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
650                 if (!bp->enabled && atomic_read(&bp->ref_count) == 0) {
651                         bp->address = a;
652                         bp->instr[1] = bpinstr;
653                         store_inst(&bp->instr[1]);
654                         return bp;
655                 }
656         }
657
658         printf("Sorry, no free breakpoints.  Please clear one first.\n");
659         return NULL;
660 }
661
662 static void insert_bpts(void)
663 {
664         int i;
665         struct bpt *bp;
666
667         bp = bpts;
668         for (i = 0; i < NBPTS; ++i, ++bp) {
669                 if ((bp->enabled & (BP_TRAP|BP_IABR)) == 0)
670                         continue;
671                 if (mread(bp->address, &bp->instr[0], 4) != 4) {
672                         printf("Couldn't read instruction at %lx, "
673                                "disabling breakpoint there\n", bp->address);
674                         bp->enabled = 0;
675                         continue;
676                 }
677                 if (IS_MTMSRD(bp->instr[0]) || IS_RFID(bp->instr[0])) {
678                         printf("Breakpoint at %lx is on an mtmsrd or rfid "
679                                "instruction, disabling it\n", bp->address);
680                         bp->enabled = 0;
681                         continue;
682                 }
683                 store_inst(&bp->instr[0]);
684                 if (bp->enabled & BP_IABR)
685                         continue;
686                 if (mwrite(bp->address, &bpinstr, 4) != 4) {
687                         printf("Couldn't write instruction at %lx, "
688                                "disabling breakpoint there\n", bp->address);
689                         bp->enabled &= ~BP_TRAP;
690                         continue;
691                 }
692                 store_inst((void *)bp->address);
693         }
694 }
695
696 static void insert_cpu_bpts(void)
697 {
698         if (dabr.enabled)
699                 set_dabr(dabr.address | (dabr.enabled & 7));
700         if (iabr && cpu_has_feature(CPU_FTR_IABR))
701                 mtspr(SPRN_IABR, iabr->address
702                          | (iabr->enabled & (BP_IABR|BP_IABR_TE)));
703 }
704
705 static void remove_bpts(void)
706 {
707         int i;
708         struct bpt *bp;
709         unsigned instr;
710
711         bp = bpts;
712         for (i = 0; i < NBPTS; ++i, ++bp) {
713                 if ((bp->enabled & (BP_TRAP|BP_IABR)) != BP_TRAP)
714                         continue;
715                 if (mread(bp->address, &instr, 4) == 4
716                     && instr == bpinstr
717                     && mwrite(bp->address, &bp->instr, 4) != 4)
718                         printf("Couldn't remove breakpoint at %lx\n",
719                                bp->address);
720                 else
721                         store_inst((void *)bp->address);
722         }
723 }
724
725 static void remove_cpu_bpts(void)
726 {
727         set_dabr(0);
728         if (cpu_has_feature(CPU_FTR_IABR))
729                 mtspr(SPRN_IABR, 0);
730 }
731
732 /* Command interpreting routine */
733 static char *last_cmd;
734
735 static int
736 cmds(struct pt_regs *excp)
737 {
738         int cmd = 0;
739
740         last_cmd = NULL;
741         xmon_regs = excp;
742         for(;;) {
743 #ifdef CONFIG_SMP
744                 printf("%x:", smp_processor_id());
745 #endif /* CONFIG_SMP */
746                 printf("mon> ");
747                 flush_input();
748                 termch = 0;
749                 cmd = skipbl();
750                 if( cmd == '\n' ) {
751                         if (last_cmd == NULL)
752                                 continue;
753                         take_input(last_cmd);
754                         last_cmd = NULL;
755                         cmd = inchar();
756                 }
757                 switch (cmd) {
758                 case 'm':
759                         cmd = inchar();
760                         switch (cmd) {
761                         case 'm':
762                         case 's':
763                         case 'd':
764                                 memops(cmd);
765                                 break;
766                         case 'l':
767                                 memlocate();
768                                 break;
769                         case 'z':
770                                 memzcan();
771                                 break;
772                         case 'i':
773                                 show_mem();
774                                 break;
775                         default:
776                                 termch = cmd;
777                                 memex();
778                         }
779                         break;
780                 case 'd':
781                         dump();
782                         break;
783                 case 'l':
784                         symbol_lookup();
785                         break;
786                 case 'r':
787                         prregs(excp);   /* print regs */
788                         break;
789                 case 'e':
790                         excprint(excp);
791                         break;
792                 case 'S':
793                         super_regs();
794                         break;
795                 case 't':
796                         backtrace(excp);
797                         break;
798                 case 'f':
799                         cacheflush();
800                         break;
801                 case 's':
802                         if (do_step(excp))
803                                 return cmd;
804                         break;
805                 case 'x':
806                 case 'X':
807                 case EOF:
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 (addr < KERNELBASE) {
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 (dabr.address < KERNELBASE) {
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 opd[3];
1471         unsigned long ret = -1UL;
1472
1473         instrs[0] = 0x7c6002a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
1474         instrs[1] = 0x4e800020;
1475         opd[0] = (unsigned long)instrs;
1476         opd[1] = 0;
1477         opd[2] = 0;
1478         store_inst(instrs);
1479         store_inst(instrs+1);
1480         code = (unsigned long (*)(void)) opd;
1481
1482         if (setjmp(bus_error_jmp) == 0) {
1483                 catch_memory_errors = 1;
1484                 sync();
1485
1486                 ret = code();
1487
1488                 sync();
1489                 /* wait a little while to see if we get a machine check */
1490                 __delay(200);
1491                 n = size;
1492         }
1493
1494         return ret;
1495 }
1496
1497 void
1498 write_spr(int n, unsigned long val)
1499 {
1500         unsigned int instrs[2];
1501         unsigned long (*code)(unsigned long);
1502         unsigned long opd[3];
1503
1504         instrs[0] = 0x7c6003a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
1505         instrs[1] = 0x4e800020;
1506         opd[0] = (unsigned long)instrs;
1507         opd[1] = 0;
1508         opd[2] = 0;
1509         store_inst(instrs);
1510         store_inst(instrs+1);
1511         code = (unsigned long (*)(unsigned long)) opd;
1512
1513         if (setjmp(bus_error_jmp) == 0) {
1514                 catch_memory_errors = 1;
1515                 sync();
1516
1517                 code(val);
1518
1519                 sync();
1520                 /* wait a little while to see if we get a machine check */
1521                 __delay(200);
1522                 n = size;
1523         }
1524 }
1525
1526 static unsigned long regno;
1527 extern char exc_prolog;
1528 extern char dec_exc;
1529
1530 void super_regs(void)
1531 {
1532         int cmd;
1533         unsigned long val;
1534 #ifdef CONFIG_PPC_ISERIES
1535         struct paca_struct *ptrPaca = NULL;
1536         struct lppaca *ptrLpPaca = NULL;
1537         struct ItLpRegSave *ptrLpRegSave = NULL;
1538 #endif
1539
1540         cmd = skipbl();
1541         if (cmd == '\n') {
1542                 unsigned long sp, toc;
1543                 asm("mr %0,1" : "=r" (sp) :);
1544                 asm("mr %0,2" : "=r" (toc) :);
1545
1546                 printf("msr  = "REG"  sprg0= "REG"\n",
1547                        mfmsr(), mfspr(SPRN_SPRG0));
1548                 printf("pvr  = "REG"  sprg1= "REG"\n",
1549                        mfspr(SPRN_PVR), mfspr(SPRN_SPRG1)); 
1550                 printf("dec  = "REG"  sprg2= "REG"\n",
1551                        mfspr(SPRN_DEC), mfspr(SPRN_SPRG2));
1552                 printf("sp   = "REG"  sprg3= "REG"\n", sp, mfspr(SPRN_SPRG3));
1553                 printf("toc  = "REG"  dar  = "REG"\n", toc, mfspr(SPRN_DAR));
1554 #ifdef CONFIG_PPC_ISERIES
1555                 // Dump out relevant Paca data areas.
1556                 printf("Paca: \n");
1557                 ptrPaca = get_paca();
1558     
1559                 printf("  Local Processor Control Area (LpPaca): \n");
1560                 ptrLpPaca = ptrPaca->lppaca_ptr;
1561                 printf("    Saved Srr0=%.16lx  Saved Srr1=%.16lx \n",
1562                        ptrLpPaca->saved_srr0, ptrLpPaca->saved_srr1);
1563                 printf("    Saved Gpr3=%.16lx  Saved Gpr4=%.16lx \n",
1564                        ptrLpPaca->saved_gpr3, ptrLpPaca->saved_gpr4);
1565                 printf("    Saved Gpr5=%.16lx \n", ptrLpPaca->saved_gpr5);
1566     
1567                 printf("  Local Processor Register Save Area (LpRegSave): \n");
1568                 ptrLpRegSave = ptrPaca->reg_save_ptr;
1569                 printf("    Saved Sprg0=%.16lx  Saved Sprg1=%.16lx \n",
1570                        ptrLpRegSave->xSPRG0, ptrLpRegSave->xSPRG0);
1571                 printf("    Saved Sprg2=%.16lx  Saved Sprg3=%.16lx \n",
1572                        ptrLpRegSave->xSPRG2, ptrLpRegSave->xSPRG3);
1573                 printf("    Saved Msr  =%.16lx  Saved Nia  =%.16lx \n",
1574                        ptrLpRegSave->xMSR, ptrLpRegSave->xNIA);
1575 #endif
1576
1577                 return;
1578         }
1579
1580         scanhex(&regno);
1581         switch (cmd) {
1582         case 'w':
1583                 val = read_spr(regno);
1584                 scanhex(&val);
1585                 write_spr(regno, val);
1586                 /* fall through */
1587         case 'r':
1588                 printf("spr %lx = %lx\n", regno, read_spr(regno));
1589                 break;
1590         }
1591         scannl();
1592 }
1593
1594 /*
1595  * Stuff for reading and writing memory safely
1596  */
1597 int
1598 mread(unsigned long adrs, void *buf, int size)
1599 {
1600         volatile int n;
1601         char *p, *q;
1602
1603         n = 0;
1604         if (setjmp(bus_error_jmp) == 0) {
1605                 catch_memory_errors = 1;
1606                 sync();
1607                 p = (char *)adrs;
1608                 q = (char *)buf;
1609                 switch (size) {
1610                 case 2:
1611                         *(u16 *)q = *(u16 *)p;
1612                         break;
1613                 case 4:
1614                         *(u32 *)q = *(u32 *)p;
1615                         break;
1616                 case 8:
1617                         *(u64 *)q = *(u64 *)p;
1618                         break;
1619                 default:
1620                         for( ; n < size; ++n) {
1621                                 *q++ = *p++;
1622                                 sync();
1623                         }
1624                 }
1625                 sync();
1626                 /* wait a little while to see if we get a machine check */
1627                 __delay(200);
1628                 n = size;
1629         }
1630         catch_memory_errors = 0;
1631         return n;
1632 }
1633
1634 int
1635 mwrite(unsigned long adrs, void *buf, int size)
1636 {
1637         volatile int n;
1638         char *p, *q;
1639
1640         n = 0;
1641         if (setjmp(bus_error_jmp) == 0) {
1642                 catch_memory_errors = 1;
1643                 sync();
1644                 p = (char *) adrs;
1645                 q = (char *) buf;
1646                 switch (size) {
1647                 case 2:
1648                         *(u16 *)p = *(u16 *)q;
1649                         break;
1650                 case 4:
1651                         *(u32 *)p = *(u32 *)q;
1652                         break;
1653                 case 8:
1654                         *(u64 *)p = *(u64 *)q;
1655                         break;
1656                 default:
1657                         for ( ; n < size; ++n) {
1658                                 *p++ = *q++;
1659                                 sync();
1660                         }
1661                 }
1662                 sync();
1663                 /* wait a little while to see if we get a machine check */
1664                 __delay(200);
1665                 n = size;
1666         } else {
1667                 printf("*** Error writing address %x\n", adrs + n);
1668         }
1669         catch_memory_errors = 0;
1670         return n;
1671 }
1672
1673 static int fault_type;
1674 static int fault_except;
1675 static char *fault_chars[] = { "--", "**", "##" };
1676
1677 static int handle_fault(struct pt_regs *regs)
1678 {
1679         fault_except = TRAP(regs);
1680         switch (TRAP(regs)) {
1681         case 0x200:
1682                 fault_type = 0;
1683                 break;
1684         case 0x300:
1685         case 0x380:
1686                 fault_type = 1;
1687                 break;
1688         default:
1689                 fault_type = 2;
1690         }
1691
1692         longjmp(bus_error_jmp, 1);
1693
1694         return 0;
1695 }
1696
1697 #define SWAP(a, b, t)   ((t) = (a), (a) = (b), (b) = (t))
1698
1699 void
1700 byterev(unsigned char *val, int size)
1701 {
1702         int t;
1703         
1704         switch (size) {
1705         case 2:
1706                 SWAP(val[0], val[1], t);
1707                 break;
1708         case 4:
1709                 SWAP(val[0], val[3], t);
1710                 SWAP(val[1], val[2], t);
1711                 break;
1712         case 8: /* is there really any use for this? */
1713                 SWAP(val[0], val[7], t);
1714                 SWAP(val[1], val[6], t);
1715                 SWAP(val[2], val[5], t);
1716                 SWAP(val[3], val[4], t);
1717                 break;
1718         }
1719 }
1720
1721 static int brev;
1722 static int mnoread;
1723
1724 static char *memex_help_string = 
1725     "Memory examine command usage:\n"
1726     "m [addr] [flags] examine/change memory\n"
1727     "  addr is optional.  will start where left off.\n"
1728     "  flags may include chars from this set:\n"
1729     "    b   modify by bytes (default)\n"
1730     "    w   modify by words (2 byte)\n"
1731     "    l   modify by longs (4 byte)\n"
1732     "    d   modify by doubleword (8 byte)\n"
1733     "    r   toggle reverse byte order mode\n"
1734     "    n   do not read memory (for i/o spaces)\n"
1735     "    .   ok to read (default)\n"
1736     "NOTE: flags are saved as defaults\n"
1737     "";
1738
1739 static char *memex_subcmd_help_string = 
1740     "Memory examine subcommands:\n"
1741     "  hexval   write this val to current location\n"
1742     "  'string' write chars from string to this location\n"
1743     "  '        increment address\n"
1744     "  ^        decrement address\n"
1745     "  /        increment addr by 0x10.  //=0x100, ///=0x1000, etc\n"
1746     "  \\        decrement addr by 0x10.  \\\\=0x100, \\\\\\=0x1000, etc\n"
1747     "  `        clear no-read flag\n"
1748     "  ;        stay at this addr\n"
1749     "  v        change to byte mode\n"
1750     "  w        change to word (2 byte) mode\n"
1751     "  l        change to long (4 byte) mode\n"
1752     "  u        change to doubleword (8 byte) mode\n"
1753     "  m addr   change current addr\n"
1754     "  n        toggle no-read flag\n"
1755     "  r        toggle byte reverse flag\n"
1756     "  < count  back up count bytes\n"
1757     "  > count  skip forward count bytes\n"
1758     "  x        exit this mode\n"
1759     "";
1760
1761 void
1762 memex(void)
1763 {
1764         int cmd, inc, i, nslash;
1765         unsigned long n;
1766         unsigned char val[16];
1767
1768         scanhex((void *)&adrs);
1769         cmd = skipbl();
1770         if (cmd == '?') {
1771                 printf(memex_help_string);
1772                 return;
1773         } else {
1774                 termch = cmd;
1775         }
1776         last_cmd = "m\n";
1777         while ((cmd = skipbl()) != '\n') {
1778                 switch( cmd ){
1779                 case 'b':       size = 1;       break;
1780                 case 'w':       size = 2;       break;
1781                 case 'l':       size = 4;       break;
1782                 case 'd':       size = 8;       break;
1783                 case 'r':       brev = !brev;   break;
1784                 case 'n':       mnoread = 1;    break;
1785                 case '.':       mnoread = 0;    break;
1786                 }
1787         }
1788         if( size <= 0 )
1789                 size = 1;
1790         else if( size > 8 )
1791                 size = 8;
1792         for(;;){
1793                 if (!mnoread)
1794                         n = mread(adrs, val, size);
1795                 printf(REG"%c", adrs, brev? 'r': ' ');
1796                 if (!mnoread) {
1797                         if (brev)
1798                                 byterev(val, size);
1799                         putchar(' ');
1800                         for (i = 0; i < n; ++i)
1801                                 printf("%.2x", val[i]);
1802                         for (; i < size; ++i)
1803                                 printf("%s", fault_chars[fault_type]);
1804                 }
1805                 putchar(' ');
1806                 inc = size;
1807                 nslash = 0;
1808                 for(;;){
1809                         if( scanhex(&n) ){
1810                                 for (i = 0; i < size; ++i)
1811                                         val[i] = n >> (i * 8);
1812                                 if (!brev)
1813                                         byterev(val, size);
1814                                 mwrite(adrs, val, size);
1815                                 inc = size;
1816                         }
1817                         cmd = skipbl();
1818                         if (cmd == '\n')
1819                                 break;
1820                         inc = 0;
1821                         switch (cmd) {
1822                         case '\'':
1823                                 for(;;){
1824                                         n = inchar();
1825                                         if( n == '\\' )
1826                                                 n = bsesc();
1827                                         else if( n == '\'' )
1828                                                 break;
1829                                         for (i = 0; i < size; ++i)
1830                                                 val[i] = n >> (i * 8);
1831                                         if (!brev)
1832                                                 byterev(val, size);
1833                                         mwrite(adrs, val, size);
1834                                         adrs += size;
1835                                 }
1836                                 adrs -= size;
1837                                 inc = size;
1838                                 break;
1839                         case ',':
1840                                 adrs += size;
1841                                 break;
1842                         case '.':
1843                                 mnoread = 0;
1844                                 break;
1845                         case ';':
1846                                 break;
1847                         case 'x':
1848                         case EOF:
1849                                 scannl();
1850                                 return;
1851                         case 'b':
1852                         case 'v':
1853                                 size = 1;
1854                                 break;
1855                         case 'w':
1856                                 size = 2;
1857                                 break;
1858                         case 'l':
1859                                 size = 4;
1860                                 break;
1861                         case 'u':
1862                                 size = 8;
1863                                 break;
1864                         case '^':
1865                                 adrs -= size;
1866                                 break;
1867                                 break;
1868                         case '/':
1869                                 if (nslash > 0)
1870                                         adrs -= 1 << nslash;
1871                                 else
1872                                         nslash = 0;
1873                                 nslash += 4;
1874                                 adrs += 1 << nslash;
1875                                 break;
1876                         case '\\':
1877                                 if (nslash < 0)
1878                                         adrs += 1 << -nslash;
1879                                 else
1880                                         nslash = 0;
1881                                 nslash -= 4;
1882                                 adrs -= 1 << -nslash;
1883                                 break;
1884                         case 'm':
1885                                 scanhex((void *)&adrs);
1886                                 break;
1887                         case 'n':
1888                                 mnoread = 1;
1889                                 break;
1890                         case 'r':
1891                                 brev = !brev;
1892                                 break;
1893                         case '<':
1894                                 n = size;
1895                                 scanhex(&n);
1896                                 adrs -= n;
1897                                 break;
1898                         case '>':
1899                                 n = size;
1900                                 scanhex(&n);
1901                                 adrs += n;
1902                                 break;
1903                         case '?':
1904                                 printf(memex_subcmd_help_string);
1905                                 break;
1906                         }
1907                 }
1908                 adrs += inc;
1909         }
1910 }
1911
1912 int
1913 bsesc(void)
1914 {
1915         int c;
1916
1917         c = inchar();
1918         switch( c ){
1919         case 'n':       c = '\n';       break;
1920         case 'r':       c = '\r';       break;
1921         case 'b':       c = '\b';       break;
1922         case 't':       c = '\t';       break;
1923         }
1924         return c;
1925 }
1926
1927 #define isxdigit(c)     (('0' <= (c) && (c) <= '9') \
1928                          || ('a' <= (c) && (c) <= 'f') \
1929                          || ('A' <= (c) && (c) <= 'F'))
1930 void
1931 dump(void)
1932 {
1933         int c;
1934
1935         c = inchar();
1936         if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')
1937                 termch = c;
1938         scanhex((void *)&adrs);
1939         if (termch != '\n')
1940                 termch = 0;
1941         if (c == 'i') {
1942                 scanhex(&nidump);
1943                 if (nidump == 0)
1944                         nidump = 16;
1945                 else if (nidump > MAX_DUMP)
1946                         nidump = MAX_DUMP;
1947                 adrs += ppc_inst_dump(adrs, nidump, 1);
1948                 last_cmd = "di\n";
1949         } else {
1950                 scanhex(&ndump);
1951                 if (ndump == 0)
1952                         ndump = 64;
1953                 else if (ndump > MAX_DUMP)
1954                         ndump = MAX_DUMP;
1955                 prdump(adrs, ndump);
1956                 adrs += ndump;
1957                 last_cmd = "d\n";
1958         }
1959 }
1960
1961 void
1962 prdump(unsigned long adrs, long ndump)
1963 {
1964         long n, m, c, r, nr;
1965         unsigned char temp[16];
1966
1967         for (n = ndump; n > 0;) {
1968                 printf(REG, adrs);
1969                 putchar(' ');
1970                 r = n < 16? n: 16;
1971                 nr = mread(adrs, temp, r);
1972                 adrs += nr;
1973                 for (m = 0; m < r; ++m) {
1974                         if ((m & (sizeof(long) - 1)) == 0 && m > 0)
1975                                 putchar(' ');
1976                         if (m < nr)
1977                                 printf("%.2x", temp[m]);
1978                         else
1979                                 printf("%s", fault_chars[fault_type]);
1980                 }
1981                 for (; m < 16; ++m) {
1982                         if ((m & (sizeof(long) - 1)) == 0)
1983                                 putchar(' ');
1984                         printf("  ");
1985                 }
1986                 printf("  |");
1987                 for (m = 0; m < r; ++m) {
1988                         if (m < nr) {
1989                                 c = temp[m];
1990                                 putchar(' ' <= c && c <= '~'? c: '.');
1991                         } else
1992                                 putchar(' ');
1993                 }
1994                 n -= r;
1995                 for (; m < 16; ++m)
1996                         putchar(' ');
1997                 printf("|\n");
1998                 if (nr < r)
1999                         break;
2000         }
2001 }
2002
2003 int
2004 ppc_inst_dump(unsigned long adr, long count, int praddr)
2005 {
2006         int nr, dotted;
2007         unsigned long first_adr;
2008         unsigned long inst, last_inst = 0;
2009         unsigned char val[4];
2010
2011         dotted = 0;
2012         for (first_adr = adr; count > 0; --count, adr += 4) {
2013                 nr = mread(adr, val, 4);
2014                 if (nr == 0) {
2015                         if (praddr) {
2016                                 const char *x = fault_chars[fault_type];
2017                                 printf(REG"  %s%s%s%s\n", adr, x, x, x, x);
2018                         }
2019                         break;
2020                 }
2021                 inst = GETWORD(val);
2022                 if (adr > first_adr && inst == last_inst) {
2023                         if (!dotted) {
2024                                 printf(" ...\n");
2025                                 dotted = 1;
2026                         }
2027                         continue;
2028                 }
2029                 dotted = 0;
2030                 last_inst = inst;
2031                 if (praddr)
2032                         printf(REG"  %.8x", adr, inst);
2033                 printf("\t");
2034                 print_insn_powerpc(inst, adr, 0);       /* always returns 4 */
2035                 printf("\n");
2036         }
2037         return adr - first_adr;
2038 }
2039
2040 void
2041 print_address(unsigned long addr)
2042 {
2043         xmon_print_symbol(addr, "\t# ", "");
2044 }
2045
2046
2047 /*
2048  * Memory operations - move, set, print differences
2049  */
2050 static unsigned long mdest;             /* destination address */
2051 static unsigned long msrc;              /* source address */
2052 static unsigned long mval;              /* byte value to set memory to */
2053 static unsigned long mcount;            /* # bytes to affect */
2054 static unsigned long mdiffs;            /* max # differences to print */
2055
2056 void
2057 memops(int cmd)
2058 {
2059         scanhex((void *)&mdest);
2060         if( termch != '\n' )
2061                 termch = 0;
2062         scanhex((void *)(cmd == 's'? &mval: &msrc));
2063         if( termch != '\n' )
2064                 termch = 0;
2065         scanhex((void *)&mcount);
2066         switch( cmd ){
2067         case 'm':
2068                 memmove((void *)mdest, (void *)msrc, mcount);
2069                 break;
2070         case 's':
2071                 memset((void *)mdest, mval, mcount);
2072                 break;
2073         case 'd':
2074                 if( termch != '\n' )
2075                         termch = 0;
2076                 scanhex((void *)&mdiffs);
2077                 memdiffs((unsigned char *)mdest, (unsigned char *)msrc, mcount, mdiffs);
2078                 break;
2079         }
2080 }
2081
2082 void
2083 memdiffs(unsigned char *p1, unsigned char *p2, unsigned nb, unsigned maxpr)
2084 {
2085         unsigned n, prt;
2086
2087         prt = 0;
2088         for( n = nb; n > 0; --n )
2089                 if( *p1++ != *p2++ )
2090                         if( ++prt <= maxpr )
2091                                 printf("%.16x %.2x # %.16x %.2x\n", p1 - 1,
2092                                         p1[-1], p2 - 1, p2[-1]);
2093         if( prt > maxpr )
2094                 printf("Total of %d differences\n", prt);
2095 }
2096
2097 static unsigned mend;
2098 static unsigned mask;
2099
2100 void
2101 memlocate(void)
2102 {
2103         unsigned a, n;
2104         unsigned char val[4];
2105
2106         last_cmd = "ml";
2107         scanhex((void *)&mdest);
2108         if (termch != '\n') {
2109                 termch = 0;
2110                 scanhex((void *)&mend);
2111                 if (termch != '\n') {
2112                         termch = 0;
2113                         scanhex((void *)&mval);
2114                         mask = ~0;
2115                         if (termch != '\n') termch = 0;
2116                         scanhex((void *)&mask);
2117                 }
2118         }
2119         n = 0;
2120         for (a = mdest; a < mend; a += 4) {
2121                 if (mread(a, val, 4) == 4
2122                         && ((GETWORD(val) ^ mval) & mask) == 0) {
2123                         printf("%.16x:  %.16x\n", a, GETWORD(val));
2124                         if (++n >= 10)
2125                                 break;
2126                 }
2127         }
2128 }
2129
2130 static unsigned long mskip = 0x1000;
2131 static unsigned long mlim = 0xffffffff;
2132
2133 void
2134 memzcan(void)
2135 {
2136         unsigned char v;
2137         unsigned a;
2138         int ok, ook;
2139
2140         scanhex(&mdest);
2141         if (termch != '\n') termch = 0;
2142         scanhex(&mskip);
2143         if (termch != '\n') termch = 0;
2144         scanhex(&mlim);
2145         ook = 0;
2146         for (a = mdest; a < mlim; a += mskip) {
2147                 ok = mread(a, &v, 1);
2148                 if (ok && !ook) {
2149                         printf("%.8x .. ", a);
2150                 } else if (!ok && ook)
2151                         printf("%.8x\n", a - mskip);
2152                 ook = ok;
2153                 if (a + mskip < a)
2154                         break;
2155         }
2156         if (ook)
2157                 printf("%.8x\n", a - mskip);
2158 }
2159
2160 void proccall(void)
2161 {
2162         unsigned long args[8];
2163         unsigned long ret;
2164         int i;
2165         typedef unsigned long (*callfunc_t)(unsigned long, unsigned long,
2166                         unsigned long, unsigned long, unsigned long,
2167                         unsigned long, unsigned long, unsigned long);
2168         callfunc_t func;
2169
2170         if (!scanhex(&adrs))
2171                 return;
2172         if (termch != '\n')
2173                 termch = 0;
2174         for (i = 0; i < 8; ++i)
2175                 args[i] = 0;
2176         for (i = 0; i < 8; ++i) {
2177                 if (!scanhex(&args[i]) || termch == '\n')
2178                         break;
2179                 termch = 0;
2180         }
2181         func = (callfunc_t) adrs;
2182         ret = 0;
2183         if (setjmp(bus_error_jmp) == 0) {
2184                 catch_memory_errors = 1;
2185                 sync();
2186                 ret = func(args[0], args[1], args[2], args[3],
2187                            args[4], args[5], args[6], args[7]);
2188                 sync();
2189                 printf("return value is %x\n", ret);
2190         } else {
2191                 printf("*** %x exception occurred\n", fault_except);
2192         }
2193         catch_memory_errors = 0;
2194 }
2195
2196 /* Input scanning routines */
2197 int
2198 skipbl(void)
2199 {
2200         int c;
2201
2202         if( termch != 0 ){
2203                 c = termch;
2204                 termch = 0;
2205         } else
2206                 c = inchar();
2207         while( c == ' ' || c == '\t' )
2208                 c = inchar();
2209         return c;
2210 }
2211
2212 #define N_PTREGS        44
2213 static char *regnames[N_PTREGS] = {
2214         "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
2215         "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
2216         "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
2217         "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
2218         "pc", "msr", "or3", "ctr", "lr", "xer", "ccr",
2219 #ifdef CONFIG_PPC64
2220         "softe",
2221 #else
2222         "mq",
2223 #endif
2224         "trap", "dar", "dsisr", "res"
2225 };
2226
2227 int
2228 scanhex(unsigned long *vp)
2229 {
2230         int c, d;
2231         unsigned long v;
2232
2233         c = skipbl();
2234         if (c == '%') {
2235                 /* parse register name */
2236                 char regname[8];
2237                 int i;
2238
2239                 for (i = 0; i < sizeof(regname) - 1; ++i) {
2240                         c = inchar();
2241                         if (!isalnum(c)) {
2242                                 termch = c;
2243                                 break;
2244                         }
2245                         regname[i] = c;
2246                 }
2247                 regname[i] = 0;
2248                 for (i = 0; i < N_PTREGS; ++i) {
2249                         if (strcmp(regnames[i], regname) == 0) {
2250                                 if (xmon_regs == NULL) {
2251                                         printf("regs not available\n");
2252                                         return 0;
2253                                 }
2254                                 *vp = ((unsigned long *)xmon_regs)[i];
2255                                 return 1;
2256                         }
2257                 }
2258                 printf("invalid register name '%%%s'\n", regname);
2259                 return 0;
2260         }
2261
2262         /* skip leading "0x" if any */
2263
2264         if (c == '0') {
2265                 c = inchar();
2266                 if (c == 'x') {
2267                         c = inchar();
2268                 } else {
2269                         d = hexdigit(c);
2270                         if (d == EOF) {
2271                                 termch = c;
2272                                 *vp = 0;
2273                                 return 1;
2274                         }
2275                 }
2276         } else if (c == '$') {
2277                 int i;
2278                 for (i=0; i<63; i++) {
2279                         c = inchar();
2280                         if (isspace(c)) {
2281                                 termch = c;
2282                                 break;
2283                         }
2284                         tmpstr[i] = c;
2285                 }
2286                 tmpstr[i++] = 0;
2287                 *vp = 0;
2288                 if (setjmp(bus_error_jmp) == 0) {
2289                         catch_memory_errors = 1;
2290                         sync();
2291                         *vp = kallsyms_lookup_name(tmpstr);
2292                         sync();
2293                 }
2294                 catch_memory_errors = 0;
2295                 if (!(*vp)) {
2296                         printf("unknown symbol '%s'\n", tmpstr);
2297                         return 0;
2298                 }
2299                 return 1;
2300         }
2301
2302         d = hexdigit(c);
2303         if (d == EOF) {
2304                 termch = c;
2305                 return 0;
2306         }
2307         v = 0;
2308         do {
2309                 v = (v << 4) + d;
2310                 c = inchar();
2311                 d = hexdigit(c);
2312         } while (d != EOF);
2313         termch = c;
2314         *vp = v;
2315         return 1;
2316 }
2317
2318 void
2319 scannl(void)
2320 {
2321         int c;
2322
2323         c = termch;
2324         termch = 0;
2325         while( c != '\n' )
2326                 c = inchar();
2327 }
2328
2329 int hexdigit(int c)
2330 {
2331         if( '0' <= c && c <= '9' )
2332                 return c - '0';
2333         if( 'A' <= c && c <= 'F' )
2334                 return c - ('A' - 10);
2335         if( 'a' <= c && c <= 'f' )
2336                 return c - ('a' - 10);
2337         return EOF;
2338 }
2339
2340 void
2341 getstring(char *s, int size)
2342 {
2343         int c;
2344
2345         c = skipbl();
2346         do {
2347                 if( size > 1 ){
2348                         *s++ = c;
2349                         --size;
2350                 }
2351                 c = inchar();
2352         } while( c != ' ' && c != '\t' && c != '\n' );
2353         termch = c;
2354         *s = 0;
2355 }
2356
2357 static char line[256];
2358 static char *lineptr;
2359
2360 void
2361 flush_input(void)
2362 {
2363         lineptr = NULL;
2364 }
2365
2366 int
2367 inchar(void)
2368 {
2369         if (lineptr == NULL || *lineptr == 0) {
2370                 if (xmon_gets(line, sizeof(line)) == NULL) {
2371                         lineptr = NULL;
2372                         return EOF;
2373                 }
2374                 lineptr = line;
2375         }
2376         return *lineptr++;
2377 }
2378
2379 void
2380 take_input(char *str)
2381 {
2382         lineptr = str;
2383 }
2384
2385
2386 static void
2387 symbol_lookup(void)
2388 {
2389         int type = inchar();
2390         unsigned long addr;
2391         static char tmp[64];
2392
2393         switch (type) {
2394         case 'a':
2395                 if (scanhex(&addr))
2396                         xmon_print_symbol(addr, ": ", "\n");
2397                 termch = 0;
2398                 break;
2399         case 's':
2400                 getstring(tmp, 64);
2401                 if (setjmp(bus_error_jmp) == 0) {
2402                         catch_memory_errors = 1;
2403                         sync();
2404                         addr = kallsyms_lookup_name(tmp);
2405                         if (addr)
2406                                 printf("%s: %lx\n", tmp, addr);
2407                         else
2408                                 printf("Symbol '%s' not found.\n", tmp);
2409                         sync();
2410                 }
2411                 catch_memory_errors = 0;
2412                 termch = 0;
2413                 break;
2414         }
2415 }
2416
2417
2418 /* Print an address in numeric and symbolic form (if possible) */
2419 static void xmon_print_symbol(unsigned long address, const char *mid,
2420                               const char *after)
2421 {
2422         char *modname;
2423         const char *name = NULL;
2424         unsigned long offset, size;
2425
2426         printf(REG, address);
2427         if (setjmp(bus_error_jmp) == 0) {
2428                 catch_memory_errors = 1;
2429                 sync();
2430                 name = kallsyms_lookup(address, &size, &offset, &modname,
2431                                        tmpstr);
2432                 sync();
2433                 /* wait a little while to see if we get a machine check */
2434                 __delay(200);
2435         }
2436
2437         catch_memory_errors = 0;
2438
2439         if (name) {
2440                 printf("%s%s+%#lx/%#lx", mid, name, offset, size);
2441                 if (modname)
2442                         printf(" [%s]", modname);
2443         }
2444         printf("%s", after);
2445 }
2446
2447 #ifdef CONFIG_PPC64
2448 static void dump_slb(void)
2449 {
2450         int i;
2451         unsigned long tmp;
2452
2453         printf("SLB contents of cpu %x\n", smp_processor_id());
2454
2455         for (i = 0; i < SLB_NUM_ENTRIES; i++) {
2456                 asm volatile("slbmfee  %0,%1" : "=r" (tmp) : "r" (i));
2457                 printf("%02d %016lx ", i, tmp);
2458
2459                 asm volatile("slbmfev  %0,%1" : "=r" (tmp) : "r" (i));
2460                 printf("%016lx\n", tmp);
2461         }
2462 }
2463
2464 static void dump_stab(void)
2465 {
2466         int i;
2467         unsigned long *tmp = (unsigned long *)get_paca()->stab_addr;
2468
2469         printf("Segment table contents of cpu %x\n", smp_processor_id());
2470
2471         for (i = 0; i < PAGE_SIZE/16; i++) {
2472                 unsigned long a, b;
2473
2474                 a = *tmp++;
2475                 b = *tmp++;
2476
2477                 if (a || b) {
2478                         printf("%03d %016lx ", i, a);
2479                         printf("%016lx\n", b);
2480                 }
2481         }
2482 }
2483
2484 void dump_segments(void)
2485 {
2486         if (cpu_has_feature(CPU_FTR_SLB))
2487                 dump_slb();
2488         else
2489                 dump_stab();
2490 }
2491 #endif
2492
2493 #ifdef CONFIG_PPC_STD_MMU_32
2494 void dump_segments(void)
2495 {
2496         int i;
2497
2498         printf("sr0-15 =");
2499         for (i = 0; i < 16; ++i)
2500                 printf(" %x", mfsrin(i));
2501         printf("\n");
2502 }
2503 #endif
2504
2505 void xmon_init(int enable)
2506 {
2507         if (enable) {
2508                 __debugger = xmon;
2509                 __debugger_ipi = xmon_ipi;
2510                 __debugger_bpt = xmon_bpt;
2511                 __debugger_sstep = xmon_sstep;
2512                 __debugger_iabr_match = xmon_iabr_match;
2513                 __debugger_dabr_match = xmon_dabr_match;
2514                 __debugger_fault_handler = xmon_fault_handler;
2515         } else {
2516                 __debugger = NULL;
2517                 __debugger_ipi = NULL;
2518                 __debugger_bpt = NULL;
2519                 __debugger_sstep = NULL;
2520                 __debugger_iabr_match = NULL;
2521                 __debugger_dabr_match = NULL;
2522                 __debugger_fault_handler = NULL;
2523         }
2524         xmon_map_scc();
2525 }
2526
2527 #ifdef CONFIG_MAGIC_SYSRQ
2528 static void sysrq_handle_xmon(int key, struct pt_regs *pt_regs,
2529                               struct tty_struct *tty) 
2530 {
2531         /* ensure xmon is enabled */
2532         xmon_init(1);
2533         debugger(pt_regs);
2534 }
2535
2536 static struct sysrq_key_op sysrq_xmon_op = 
2537 {
2538         .handler =      sysrq_handle_xmon,
2539         .help_msg =     "Xmon",
2540         .action_msg =   "Entering xmon",
2541 };
2542
2543 static int __init setup_xmon_sysrq(void)
2544 {
2545         register_sysrq_key('x', &sysrq_xmon_op);
2546         return 0;
2547 }
2548 __initcall(setup_xmon_sysrq);
2549 #endif /* CONFIG_MAGIC_SYSRQ */