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