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