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