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