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