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