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