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