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