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