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