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