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