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