Merge branch '8139-thread'
[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 ret = -1UL;
1471 #ifdef CONFIG_PPC64
1472         unsigned long opd[3];
1473
1474         opd[0] = (unsigned long)instrs;
1475         opd[1] = 0;
1476         opd[2] = 0;
1477         code = (unsigned long (*)(void)) opd;
1478 #else
1479         code = (unsigned long (*)(void)) instrs;
1480 #endif
1481
1482         /* mfspr r3,n; blr */
1483         instrs[0] = 0x7c6002a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
1484         instrs[1] = 0x4e800020;
1485         store_inst(instrs);
1486         store_inst(instrs+1);
1487
1488         if (setjmp(bus_error_jmp) == 0) {
1489                 catch_memory_errors = 1;
1490                 sync();
1491
1492                 ret = code();
1493
1494                 sync();
1495                 /* wait a little while to see if we get a machine check */
1496                 __delay(200);
1497                 n = size;
1498         }
1499
1500         return ret;
1501 }
1502
1503 void
1504 write_spr(int n, unsigned long val)
1505 {
1506         unsigned int instrs[2];
1507         unsigned long (*code)(unsigned long);
1508 #ifdef CONFIG_PPC64
1509         unsigned long opd[3];
1510
1511         opd[0] = (unsigned long)instrs;
1512         opd[1] = 0;
1513         opd[2] = 0;
1514         code = (unsigned long (*)(unsigned long)) opd;
1515 #else
1516         code = (unsigned long (*)(unsigned long)) instrs;
1517 #endif
1518
1519         instrs[0] = 0x7c6003a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
1520         instrs[1] = 0x4e800020;
1521         store_inst(instrs);
1522         store_inst(instrs+1);
1523
1524         if (setjmp(bus_error_jmp) == 0) {
1525                 catch_memory_errors = 1;
1526                 sync();
1527
1528                 code(val);
1529
1530                 sync();
1531                 /* wait a little while to see if we get a machine check */
1532                 __delay(200);
1533                 n = size;
1534         }
1535 }
1536
1537 static unsigned long regno;
1538 extern char exc_prolog;
1539 extern char dec_exc;
1540
1541 void super_regs(void)
1542 {
1543         int cmd;
1544         unsigned long val;
1545 #ifdef CONFIG_PPC_ISERIES
1546         struct paca_struct *ptrPaca = NULL;
1547         struct lppaca *ptrLpPaca = NULL;
1548         struct ItLpRegSave *ptrLpRegSave = NULL;
1549 #endif
1550
1551         cmd = skipbl();
1552         if (cmd == '\n') {
1553                 unsigned long sp, toc;
1554                 asm("mr %0,1" : "=r" (sp) :);
1555                 asm("mr %0,2" : "=r" (toc) :);
1556
1557                 printf("msr  = "REG"  sprg0= "REG"\n",
1558                        mfmsr(), mfspr(SPRN_SPRG0));
1559                 printf("pvr  = "REG"  sprg1= "REG"\n",
1560                        mfspr(SPRN_PVR), mfspr(SPRN_SPRG1)); 
1561                 printf("dec  = "REG"  sprg2= "REG"\n",
1562                        mfspr(SPRN_DEC), mfspr(SPRN_SPRG2));
1563                 printf("sp   = "REG"  sprg3= "REG"\n", sp, mfspr(SPRN_SPRG3));
1564                 printf("toc  = "REG"  dar  = "REG"\n", toc, mfspr(SPRN_DAR));
1565 #ifdef CONFIG_PPC_ISERIES
1566                 // Dump out relevant Paca data areas.
1567                 printf("Paca: \n");
1568                 ptrPaca = get_paca();
1569     
1570                 printf("  Local Processor Control Area (LpPaca): \n");
1571                 ptrLpPaca = ptrPaca->lppaca_ptr;
1572                 printf("    Saved Srr0=%.16lx  Saved Srr1=%.16lx \n",
1573                        ptrLpPaca->saved_srr0, ptrLpPaca->saved_srr1);
1574                 printf("    Saved Gpr3=%.16lx  Saved Gpr4=%.16lx \n",
1575                        ptrLpPaca->saved_gpr3, ptrLpPaca->saved_gpr4);
1576                 printf("    Saved Gpr5=%.16lx \n", ptrLpPaca->saved_gpr5);
1577     
1578                 printf("  Local Processor Register Save Area (LpRegSave): \n");
1579                 ptrLpRegSave = ptrPaca->reg_save_ptr;
1580                 printf("    Saved Sprg0=%.16lx  Saved Sprg1=%.16lx \n",
1581                        ptrLpRegSave->xSPRG0, ptrLpRegSave->xSPRG0);
1582                 printf("    Saved Sprg2=%.16lx  Saved Sprg3=%.16lx \n",
1583                        ptrLpRegSave->xSPRG2, ptrLpRegSave->xSPRG3);
1584                 printf("    Saved Msr  =%.16lx  Saved Nia  =%.16lx \n",
1585                        ptrLpRegSave->xMSR, ptrLpRegSave->xNIA);
1586 #endif
1587
1588                 return;
1589         }
1590
1591         scanhex(&regno);
1592         switch (cmd) {
1593         case 'w':
1594                 val = read_spr(regno);
1595                 scanhex(&val);
1596                 write_spr(regno, val);
1597                 /* fall through */
1598         case 'r':
1599                 printf("spr %lx = %lx\n", regno, read_spr(regno));
1600                 break;
1601         }
1602         scannl();
1603 }
1604
1605 /*
1606  * Stuff for reading and writing memory safely
1607  */
1608 int
1609 mread(unsigned long adrs, void *buf, int size)
1610 {
1611         volatile int n;
1612         char *p, *q;
1613
1614         n = 0;
1615         if (setjmp(bus_error_jmp) == 0) {
1616                 catch_memory_errors = 1;
1617                 sync();
1618                 p = (char *)adrs;
1619                 q = (char *)buf;
1620                 switch (size) {
1621                 case 2:
1622                         *(u16 *)q = *(u16 *)p;
1623                         break;
1624                 case 4:
1625                         *(u32 *)q = *(u32 *)p;
1626                         break;
1627                 case 8:
1628                         *(u64 *)q = *(u64 *)p;
1629                         break;
1630                 default:
1631                         for( ; n < size; ++n) {
1632                                 *q++ = *p++;
1633                                 sync();
1634                         }
1635                 }
1636                 sync();
1637                 /* wait a little while to see if we get a machine check */
1638                 __delay(200);
1639                 n = size;
1640         }
1641         catch_memory_errors = 0;
1642         return n;
1643 }
1644
1645 int
1646 mwrite(unsigned long adrs, void *buf, int size)
1647 {
1648         volatile int n;
1649         char *p, *q;
1650
1651         n = 0;
1652         if (setjmp(bus_error_jmp) == 0) {
1653                 catch_memory_errors = 1;
1654                 sync();
1655                 p = (char *) adrs;
1656                 q = (char *) buf;
1657                 switch (size) {
1658                 case 2:
1659                         *(u16 *)p = *(u16 *)q;
1660                         break;
1661                 case 4:
1662                         *(u32 *)p = *(u32 *)q;
1663                         break;
1664                 case 8:
1665                         *(u64 *)p = *(u64 *)q;
1666                         break;
1667                 default:
1668                         for ( ; n < size; ++n) {
1669                                 *p++ = *q++;
1670                                 sync();
1671                         }
1672                 }
1673                 sync();
1674                 /* wait a little while to see if we get a machine check */
1675                 __delay(200);
1676                 n = size;
1677         } else {
1678                 printf("*** Error writing address %x\n", adrs + n);
1679         }
1680         catch_memory_errors = 0;
1681         return n;
1682 }
1683
1684 static int fault_type;
1685 static int fault_except;
1686 static char *fault_chars[] = { "--", "**", "##" };
1687
1688 static int handle_fault(struct pt_regs *regs)
1689 {
1690         fault_except = TRAP(regs);
1691         switch (TRAP(regs)) {
1692         case 0x200:
1693                 fault_type = 0;
1694                 break;
1695         case 0x300:
1696         case 0x380:
1697                 fault_type = 1;
1698                 break;
1699         default:
1700                 fault_type = 2;
1701         }
1702
1703         longjmp(bus_error_jmp, 1);
1704
1705         return 0;
1706 }
1707
1708 #define SWAP(a, b, t)   ((t) = (a), (a) = (b), (b) = (t))
1709
1710 void
1711 byterev(unsigned char *val, int size)
1712 {
1713         int t;
1714         
1715         switch (size) {
1716         case 2:
1717                 SWAP(val[0], val[1], t);
1718                 break;
1719         case 4:
1720                 SWAP(val[0], val[3], t);
1721                 SWAP(val[1], val[2], t);
1722                 break;
1723         case 8: /* is there really any use for this? */
1724                 SWAP(val[0], val[7], t);
1725                 SWAP(val[1], val[6], t);
1726                 SWAP(val[2], val[5], t);
1727                 SWAP(val[3], val[4], t);
1728                 break;
1729         }
1730 }
1731
1732 static int brev;
1733 static int mnoread;
1734
1735 static char *memex_help_string = 
1736     "Memory examine command usage:\n"
1737     "m [addr] [flags] examine/change memory\n"
1738     "  addr is optional.  will start where left off.\n"
1739     "  flags may include chars from this set:\n"
1740     "    b   modify by bytes (default)\n"
1741     "    w   modify by words (2 byte)\n"
1742     "    l   modify by longs (4 byte)\n"
1743     "    d   modify by doubleword (8 byte)\n"
1744     "    r   toggle reverse byte order mode\n"
1745     "    n   do not read memory (for i/o spaces)\n"
1746     "    .   ok to read (default)\n"
1747     "NOTE: flags are saved as defaults\n"
1748     "";
1749
1750 static char *memex_subcmd_help_string = 
1751     "Memory examine subcommands:\n"
1752     "  hexval   write this val to current location\n"
1753     "  'string' write chars from string to this location\n"
1754     "  '        increment address\n"
1755     "  ^        decrement address\n"
1756     "  /        increment addr by 0x10.  //=0x100, ///=0x1000, etc\n"
1757     "  \\        decrement addr by 0x10.  \\\\=0x100, \\\\\\=0x1000, etc\n"
1758     "  `        clear no-read flag\n"
1759     "  ;        stay at this addr\n"
1760     "  v        change to byte mode\n"
1761     "  w        change to word (2 byte) mode\n"
1762     "  l        change to long (4 byte) mode\n"
1763     "  u        change to doubleword (8 byte) mode\n"
1764     "  m addr   change current addr\n"
1765     "  n        toggle no-read flag\n"
1766     "  r        toggle byte reverse flag\n"
1767     "  < count  back up count bytes\n"
1768     "  > count  skip forward count bytes\n"
1769     "  x        exit this mode\n"
1770     "";
1771
1772 void
1773 memex(void)
1774 {
1775         int cmd, inc, i, nslash;
1776         unsigned long n;
1777         unsigned char val[16];
1778
1779         scanhex((void *)&adrs);
1780         cmd = skipbl();
1781         if (cmd == '?') {
1782                 printf(memex_help_string);
1783                 return;
1784         } else {
1785                 termch = cmd;
1786         }
1787         last_cmd = "m\n";
1788         while ((cmd = skipbl()) != '\n') {
1789                 switch( cmd ){
1790                 case 'b':       size = 1;       break;
1791                 case 'w':       size = 2;       break;
1792                 case 'l':       size = 4;       break;
1793                 case 'd':       size = 8;       break;
1794                 case 'r':       brev = !brev;   break;
1795                 case 'n':       mnoread = 1;    break;
1796                 case '.':       mnoread = 0;    break;
1797                 }
1798         }
1799         if( size <= 0 )
1800                 size = 1;
1801         else if( size > 8 )
1802                 size = 8;
1803         for(;;){
1804                 if (!mnoread)
1805                         n = mread(adrs, val, size);
1806                 printf(REG"%c", adrs, brev? 'r': ' ');
1807                 if (!mnoread) {
1808                         if (brev)
1809                                 byterev(val, size);
1810                         putchar(' ');
1811                         for (i = 0; i < n; ++i)
1812                                 printf("%.2x", val[i]);
1813                         for (; i < size; ++i)
1814                                 printf("%s", fault_chars[fault_type]);
1815                 }
1816                 putchar(' ');
1817                 inc = size;
1818                 nslash = 0;
1819                 for(;;){
1820                         if( scanhex(&n) ){
1821                                 for (i = 0; i < size; ++i)
1822                                         val[i] = n >> (i * 8);
1823                                 if (!brev)
1824                                         byterev(val, size);
1825                                 mwrite(adrs, val, size);
1826                                 inc = size;
1827                         }
1828                         cmd = skipbl();
1829                         if (cmd == '\n')
1830                                 break;
1831                         inc = 0;
1832                         switch (cmd) {
1833                         case '\'':
1834                                 for(;;){
1835                                         n = inchar();
1836                                         if( n == '\\' )
1837                                                 n = bsesc();
1838                                         else if( n == '\'' )
1839                                                 break;
1840                                         for (i = 0; i < size; ++i)
1841                                                 val[i] = n >> (i * 8);
1842                                         if (!brev)
1843                                                 byterev(val, size);
1844                                         mwrite(adrs, val, size);
1845                                         adrs += size;
1846                                 }
1847                                 adrs -= size;
1848                                 inc = size;
1849                                 break;
1850                         case ',':
1851                                 adrs += size;
1852                                 break;
1853                         case '.':
1854                                 mnoread = 0;
1855                                 break;
1856                         case ';':
1857                                 break;
1858                         case 'x':
1859                         case EOF:
1860                                 scannl();
1861                                 return;
1862                         case 'b':
1863                         case 'v':
1864                                 size = 1;
1865                                 break;
1866                         case 'w':
1867                                 size = 2;
1868                                 break;
1869                         case 'l':
1870                                 size = 4;
1871                                 break;
1872                         case 'u':
1873                                 size = 8;
1874                                 break;
1875                         case '^':
1876                                 adrs -= size;
1877                                 break;
1878                                 break;
1879                         case '/':
1880                                 if (nslash > 0)
1881                                         adrs -= 1 << nslash;
1882                                 else
1883                                         nslash = 0;
1884                                 nslash += 4;
1885                                 adrs += 1 << nslash;
1886                                 break;
1887                         case '\\':
1888                                 if (nslash < 0)
1889                                         adrs += 1 << -nslash;
1890                                 else
1891                                         nslash = 0;
1892                                 nslash -= 4;
1893                                 adrs -= 1 << -nslash;
1894                                 break;
1895                         case 'm':
1896                                 scanhex((void *)&adrs);
1897                                 break;
1898                         case 'n':
1899                                 mnoread = 1;
1900                                 break;
1901                         case 'r':
1902                                 brev = !brev;
1903                                 break;
1904                         case '<':
1905                                 n = size;
1906                                 scanhex(&n);
1907                                 adrs -= n;
1908                                 break;
1909                         case '>':
1910                                 n = size;
1911                                 scanhex(&n);
1912                                 adrs += n;
1913                                 break;
1914                         case '?':
1915                                 printf(memex_subcmd_help_string);
1916                                 break;
1917                         }
1918                 }
1919                 adrs += inc;
1920         }
1921 }
1922
1923 int
1924 bsesc(void)
1925 {
1926         int c;
1927
1928         c = inchar();
1929         switch( c ){
1930         case 'n':       c = '\n';       break;
1931         case 'r':       c = '\r';       break;
1932         case 'b':       c = '\b';       break;
1933         case 't':       c = '\t';       break;
1934         }
1935         return c;
1936 }
1937
1938 #define isxdigit(c)     (('0' <= (c) && (c) <= '9') \
1939                          || ('a' <= (c) && (c) <= 'f') \
1940                          || ('A' <= (c) && (c) <= 'F'))
1941 void
1942 dump(void)
1943 {
1944         int c;
1945
1946         c = inchar();
1947         if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')
1948                 termch = c;
1949         scanhex((void *)&adrs);
1950         if (termch != '\n')
1951                 termch = 0;
1952         if (c == 'i') {
1953                 scanhex(&nidump);
1954                 if (nidump == 0)
1955                         nidump = 16;
1956                 else if (nidump > MAX_DUMP)
1957                         nidump = MAX_DUMP;
1958                 adrs += ppc_inst_dump(adrs, nidump, 1);
1959                 last_cmd = "di\n";
1960         } else {
1961                 scanhex(&ndump);
1962                 if (ndump == 0)
1963                         ndump = 64;
1964                 else if (ndump > MAX_DUMP)
1965                         ndump = MAX_DUMP;
1966                 prdump(adrs, ndump);
1967                 adrs += ndump;
1968                 last_cmd = "d\n";
1969         }
1970 }
1971
1972 void
1973 prdump(unsigned long adrs, long ndump)
1974 {
1975         long n, m, c, r, nr;
1976         unsigned char temp[16];
1977
1978         for (n = ndump; n > 0;) {
1979                 printf(REG, adrs);
1980                 putchar(' ');
1981                 r = n < 16? n: 16;
1982                 nr = mread(adrs, temp, r);
1983                 adrs += nr;
1984                 for (m = 0; m < r; ++m) {
1985                         if ((m & (sizeof(long) - 1)) == 0 && m > 0)
1986                                 putchar(' ');
1987                         if (m < nr)
1988                                 printf("%.2x", temp[m]);
1989                         else
1990                                 printf("%s", fault_chars[fault_type]);
1991                 }
1992                 for (; m < 16; ++m) {
1993                         if ((m & (sizeof(long) - 1)) == 0)
1994                                 putchar(' ');
1995                         printf("  ");
1996                 }
1997                 printf("  |");
1998                 for (m = 0; m < r; ++m) {
1999                         if (m < nr) {
2000                                 c = temp[m];
2001                                 putchar(' ' <= c && c <= '~'? c: '.');
2002                         } else
2003                                 putchar(' ');
2004                 }
2005                 n -= r;
2006                 for (; m < 16; ++m)
2007                         putchar(' ');
2008                 printf("|\n");
2009                 if (nr < r)
2010                         break;
2011         }
2012 }
2013
2014 int
2015 ppc_inst_dump(unsigned long adr, long count, int praddr)
2016 {
2017         int nr, dotted;
2018         unsigned long first_adr;
2019         unsigned long inst, last_inst = 0;
2020         unsigned char val[4];
2021
2022         dotted = 0;
2023         for (first_adr = adr; count > 0; --count, adr += 4) {
2024                 nr = mread(adr, val, 4);
2025                 if (nr == 0) {
2026                         if (praddr) {
2027                                 const char *x = fault_chars[fault_type];
2028                                 printf(REG"  %s%s%s%s\n", adr, x, x, x, x);
2029                         }
2030                         break;
2031                 }
2032                 inst = GETWORD(val);
2033                 if (adr > first_adr && inst == last_inst) {
2034                         if (!dotted) {
2035                                 printf(" ...\n");
2036                                 dotted = 1;
2037                         }
2038                         continue;
2039                 }
2040                 dotted = 0;
2041                 last_inst = inst;
2042                 if (praddr)
2043                         printf(REG"  %.8x", adr, inst);
2044                 printf("\t");
2045                 print_insn_powerpc(inst, adr, 0);       /* always returns 4 */
2046                 printf("\n");
2047         }
2048         return adr - first_adr;
2049 }
2050
2051 void
2052 print_address(unsigned long addr)
2053 {
2054         xmon_print_symbol(addr, "\t# ", "");
2055 }
2056
2057
2058 /*
2059  * Memory operations - move, set, print differences
2060  */
2061 static unsigned long mdest;             /* destination address */
2062 static unsigned long msrc;              /* source address */
2063 static unsigned long mval;              /* byte value to set memory to */
2064 static unsigned long mcount;            /* # bytes to affect */
2065 static unsigned long mdiffs;            /* max # differences to print */
2066
2067 void
2068 memops(int cmd)
2069 {
2070         scanhex((void *)&mdest);
2071         if( termch != '\n' )
2072                 termch = 0;
2073         scanhex((void *)(cmd == 's'? &mval: &msrc));
2074         if( termch != '\n' )
2075                 termch = 0;
2076         scanhex((void *)&mcount);
2077         switch( cmd ){
2078         case 'm':
2079                 memmove((void *)mdest, (void *)msrc, mcount);
2080                 break;
2081         case 's':
2082                 memset((void *)mdest, mval, mcount);
2083                 break;
2084         case 'd':
2085                 if( termch != '\n' )
2086                         termch = 0;
2087                 scanhex((void *)&mdiffs);
2088                 memdiffs((unsigned char *)mdest, (unsigned char *)msrc, mcount, mdiffs);
2089                 break;
2090         }
2091 }
2092
2093 void
2094 memdiffs(unsigned char *p1, unsigned char *p2, unsigned nb, unsigned maxpr)
2095 {
2096         unsigned n, prt;
2097
2098         prt = 0;
2099         for( n = nb; n > 0; --n )
2100                 if( *p1++ != *p2++ )
2101                         if( ++prt <= maxpr )
2102                                 printf("%.16x %.2x # %.16x %.2x\n", p1 - 1,
2103                                         p1[-1], p2 - 1, p2[-1]);
2104         if( prt > maxpr )
2105                 printf("Total of %d differences\n", prt);
2106 }
2107
2108 static unsigned mend;
2109 static unsigned mask;
2110
2111 void
2112 memlocate(void)
2113 {
2114         unsigned a, n;
2115         unsigned char val[4];
2116
2117         last_cmd = "ml";
2118         scanhex((void *)&mdest);
2119         if (termch != '\n') {
2120                 termch = 0;
2121                 scanhex((void *)&mend);
2122                 if (termch != '\n') {
2123                         termch = 0;
2124                         scanhex((void *)&mval);
2125                         mask = ~0;
2126                         if (termch != '\n') termch = 0;
2127                         scanhex((void *)&mask);
2128                 }
2129         }
2130         n = 0;
2131         for (a = mdest; a < mend; a += 4) {
2132                 if (mread(a, val, 4) == 4
2133                         && ((GETWORD(val) ^ mval) & mask) == 0) {
2134                         printf("%.16x:  %.16x\n", a, GETWORD(val));
2135                         if (++n >= 10)
2136                                 break;
2137                 }
2138         }
2139 }
2140
2141 static unsigned long mskip = 0x1000;
2142 static unsigned long mlim = 0xffffffff;
2143
2144 void
2145 memzcan(void)
2146 {
2147         unsigned char v;
2148         unsigned a;
2149         int ok, ook;
2150
2151         scanhex(&mdest);
2152         if (termch != '\n') termch = 0;
2153         scanhex(&mskip);
2154         if (termch != '\n') termch = 0;
2155         scanhex(&mlim);
2156         ook = 0;
2157         for (a = mdest; a < mlim; a += mskip) {
2158                 ok = mread(a, &v, 1);
2159                 if (ok && !ook) {
2160                         printf("%.8x .. ", a);
2161                 } else if (!ok && ook)
2162                         printf("%.8x\n", a - mskip);
2163                 ook = ok;
2164                 if (a + mskip < a)
2165                         break;
2166         }
2167         if (ook)
2168                 printf("%.8x\n", a - mskip);
2169 }
2170
2171 void proccall(void)
2172 {
2173         unsigned long args[8];
2174         unsigned long ret;
2175         int i;
2176         typedef unsigned long (*callfunc_t)(unsigned long, unsigned long,
2177                         unsigned long, unsigned long, unsigned long,
2178                         unsigned long, unsigned long, unsigned long);
2179         callfunc_t func;
2180
2181         if (!scanhex(&adrs))
2182                 return;
2183         if (termch != '\n')
2184                 termch = 0;
2185         for (i = 0; i < 8; ++i)
2186                 args[i] = 0;
2187         for (i = 0; i < 8; ++i) {
2188                 if (!scanhex(&args[i]) || termch == '\n')
2189                         break;
2190                 termch = 0;
2191         }
2192         func = (callfunc_t) adrs;
2193         ret = 0;
2194         if (setjmp(bus_error_jmp) == 0) {
2195                 catch_memory_errors = 1;
2196                 sync();
2197                 ret = func(args[0], args[1], args[2], args[3],
2198                            args[4], args[5], args[6], args[7]);
2199                 sync();
2200                 printf("return value is %x\n", ret);
2201         } else {
2202                 printf("*** %x exception occurred\n", fault_except);
2203         }
2204         catch_memory_errors = 0;
2205 }
2206
2207 /* Input scanning routines */
2208 int
2209 skipbl(void)
2210 {
2211         int c;
2212
2213         if( termch != 0 ){
2214                 c = termch;
2215                 termch = 0;
2216         } else
2217                 c = inchar();
2218         while( c == ' ' || c == '\t' )
2219                 c = inchar();
2220         return c;
2221 }
2222
2223 #define N_PTREGS        44
2224 static char *regnames[N_PTREGS] = {
2225         "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
2226         "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
2227         "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
2228         "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
2229         "pc", "msr", "or3", "ctr", "lr", "xer", "ccr",
2230 #ifdef CONFIG_PPC64
2231         "softe",
2232 #else
2233         "mq",
2234 #endif
2235         "trap", "dar", "dsisr", "res"
2236 };
2237
2238 int
2239 scanhex(unsigned long *vp)
2240 {
2241         int c, d;
2242         unsigned long v;
2243
2244         c = skipbl();
2245         if (c == '%') {
2246                 /* parse register name */
2247                 char regname[8];
2248                 int i;
2249
2250                 for (i = 0; i < sizeof(regname) - 1; ++i) {
2251                         c = inchar();
2252                         if (!isalnum(c)) {
2253                                 termch = c;
2254                                 break;
2255                         }
2256                         regname[i] = c;
2257                 }
2258                 regname[i] = 0;
2259                 for (i = 0; i < N_PTREGS; ++i) {
2260                         if (strcmp(regnames[i], regname) == 0) {
2261                                 if (xmon_regs == NULL) {
2262                                         printf("regs not available\n");
2263                                         return 0;
2264                                 }
2265                                 *vp = ((unsigned long *)xmon_regs)[i];
2266                                 return 1;
2267                         }
2268                 }
2269                 printf("invalid register name '%%%s'\n", regname);
2270                 return 0;
2271         }
2272
2273         /* skip leading "0x" if any */
2274
2275         if (c == '0') {
2276                 c = inchar();
2277                 if (c == 'x') {
2278                         c = inchar();
2279                 } else {
2280                         d = hexdigit(c);
2281                         if (d == EOF) {
2282                                 termch = c;
2283                                 *vp = 0;
2284                                 return 1;
2285                         }
2286                 }
2287         } else if (c == '$') {
2288                 int i;
2289                 for (i=0; i<63; i++) {
2290                         c = inchar();
2291                         if (isspace(c)) {
2292                                 termch = c;
2293                                 break;
2294                         }
2295                         tmpstr[i] = c;
2296                 }
2297                 tmpstr[i++] = 0;
2298                 *vp = 0;
2299                 if (setjmp(bus_error_jmp) == 0) {
2300                         catch_memory_errors = 1;
2301                         sync();
2302                         *vp = kallsyms_lookup_name(tmpstr);
2303                         sync();
2304                 }
2305                 catch_memory_errors = 0;
2306                 if (!(*vp)) {
2307                         printf("unknown symbol '%s'\n", tmpstr);
2308                         return 0;
2309                 }
2310                 return 1;
2311         }
2312
2313         d = hexdigit(c);
2314         if (d == EOF) {
2315                 termch = c;
2316                 return 0;
2317         }
2318         v = 0;
2319         do {
2320                 v = (v << 4) + d;
2321                 c = inchar();
2322                 d = hexdigit(c);
2323         } while (d != EOF);
2324         termch = c;
2325         *vp = v;
2326         return 1;
2327 }
2328
2329 void
2330 scannl(void)
2331 {
2332         int c;
2333
2334         c = termch;
2335         termch = 0;
2336         while( c != '\n' )
2337                 c = inchar();
2338 }
2339
2340 int hexdigit(int c)
2341 {
2342         if( '0' <= c && c <= '9' )
2343                 return c - '0';
2344         if( 'A' <= c && c <= 'F' )
2345                 return c - ('A' - 10);
2346         if( 'a' <= c && c <= 'f' )
2347                 return c - ('a' - 10);
2348         return EOF;
2349 }
2350
2351 void
2352 getstring(char *s, int size)
2353 {
2354         int c;
2355
2356         c = skipbl();
2357         do {
2358                 if( size > 1 ){
2359                         *s++ = c;
2360                         --size;
2361                 }
2362                 c = inchar();
2363         } while( c != ' ' && c != '\t' && c != '\n' );
2364         termch = c;
2365         *s = 0;
2366 }
2367
2368 static char line[256];
2369 static char *lineptr;
2370
2371 void
2372 flush_input(void)
2373 {
2374         lineptr = NULL;
2375 }
2376
2377 int
2378 inchar(void)
2379 {
2380         if (lineptr == NULL || *lineptr == 0) {
2381                 if (xmon_gets(line, sizeof(line)) == NULL) {
2382                         lineptr = NULL;
2383                         return EOF;
2384                 }
2385                 lineptr = line;
2386         }
2387         return *lineptr++;
2388 }
2389
2390 void
2391 take_input(char *str)
2392 {
2393         lineptr = str;
2394 }
2395
2396
2397 static void
2398 symbol_lookup(void)
2399 {
2400         int type = inchar();
2401         unsigned long addr;
2402         static char tmp[64];
2403
2404         switch (type) {
2405         case 'a':
2406                 if (scanhex(&addr))
2407                         xmon_print_symbol(addr, ": ", "\n");
2408                 termch = 0;
2409                 break;
2410         case 's':
2411                 getstring(tmp, 64);
2412                 if (setjmp(bus_error_jmp) == 0) {
2413                         catch_memory_errors = 1;
2414                         sync();
2415                         addr = kallsyms_lookup_name(tmp);
2416                         if (addr)
2417                                 printf("%s: %lx\n", tmp, addr);
2418                         else
2419                                 printf("Symbol '%s' not found.\n", tmp);
2420                         sync();
2421                 }
2422                 catch_memory_errors = 0;
2423                 termch = 0;
2424                 break;
2425         }
2426 }
2427
2428
2429 /* Print an address in numeric and symbolic form (if possible) */
2430 static void xmon_print_symbol(unsigned long address, const char *mid,
2431                               const char *after)
2432 {
2433         char *modname;
2434         const char *name = NULL;
2435         unsigned long offset, size;
2436
2437         printf(REG, address);
2438         if (setjmp(bus_error_jmp) == 0) {
2439                 catch_memory_errors = 1;
2440                 sync();
2441                 name = kallsyms_lookup(address, &size, &offset, &modname,
2442                                        tmpstr);
2443                 sync();
2444                 /* wait a little while to see if we get a machine check */
2445                 __delay(200);
2446         }
2447
2448         catch_memory_errors = 0;
2449
2450         if (name) {
2451                 printf("%s%s+%#lx/%#lx", mid, name, offset, size);
2452                 if (modname)
2453                         printf(" [%s]", modname);
2454         }
2455         printf("%s", after);
2456 }
2457
2458 #ifdef CONFIG_PPC64
2459 static void dump_slb(void)
2460 {
2461         int i;
2462         unsigned long tmp;
2463
2464         printf("SLB contents of cpu %x\n", smp_processor_id());
2465
2466         for (i = 0; i < SLB_NUM_ENTRIES; i++) {
2467                 asm volatile("slbmfee  %0,%1" : "=r" (tmp) : "r" (i));
2468                 printf("%02d %016lx ", i, tmp);
2469
2470                 asm volatile("slbmfev  %0,%1" : "=r" (tmp) : "r" (i));
2471                 printf("%016lx\n", tmp);
2472         }
2473 }
2474
2475 static void dump_stab(void)
2476 {
2477         int i;
2478         unsigned long *tmp = (unsigned long *)get_paca()->stab_addr;
2479
2480         printf("Segment table contents of cpu %x\n", smp_processor_id());
2481
2482         for (i = 0; i < PAGE_SIZE/16; i++) {
2483                 unsigned long a, b;
2484
2485                 a = *tmp++;
2486                 b = *tmp++;
2487
2488                 if (a || b) {
2489                         printf("%03d %016lx ", i, a);
2490                         printf("%016lx\n", b);
2491                 }
2492         }
2493 }
2494
2495 void dump_segments(void)
2496 {
2497         if (cpu_has_feature(CPU_FTR_SLB))
2498                 dump_slb();
2499         else
2500                 dump_stab();
2501 }
2502 #endif
2503
2504 #ifdef CONFIG_PPC_STD_MMU_32
2505 void dump_segments(void)
2506 {
2507         int i;
2508
2509         printf("sr0-15 =");
2510         for (i = 0; i < 16; ++i)
2511                 printf(" %x", mfsrin(i));
2512         printf("\n");
2513 }
2514 #endif
2515
2516 void xmon_init(int enable)
2517 {
2518         if (enable) {
2519                 __debugger = xmon;
2520                 __debugger_ipi = xmon_ipi;
2521                 __debugger_bpt = xmon_bpt;
2522                 __debugger_sstep = xmon_sstep;
2523                 __debugger_iabr_match = xmon_iabr_match;
2524                 __debugger_dabr_match = xmon_dabr_match;
2525                 __debugger_fault_handler = xmon_fault_handler;
2526         } else {
2527                 __debugger = NULL;
2528                 __debugger_ipi = NULL;
2529                 __debugger_bpt = NULL;
2530                 __debugger_sstep = NULL;
2531                 __debugger_iabr_match = NULL;
2532                 __debugger_dabr_match = NULL;
2533                 __debugger_fault_handler = NULL;
2534         }
2535         xmon_map_scc();
2536 }
2537
2538 #ifdef CONFIG_MAGIC_SYSRQ
2539 static void sysrq_handle_xmon(int key, struct pt_regs *pt_regs,
2540                               struct tty_struct *tty) 
2541 {
2542         /* ensure xmon is enabled */
2543         xmon_init(1);
2544         debugger(pt_regs);
2545 }
2546
2547 static struct sysrq_key_op sysrq_xmon_op = 
2548 {
2549         .handler =      sysrq_handle_xmon,
2550         .help_msg =     "Xmon",
2551         .action_msg =   "Entering xmon",
2552 };
2553
2554 static int __init setup_xmon_sysrq(void)
2555 {
2556         register_sysrq_key('x', &sysrq_xmon_op);
2557         return 0;
2558 }
2559 __initcall(setup_xmon_sysrq);
2560 #endif /* CONFIG_MAGIC_SYSRQ */