Linux 3.17-rc2
[linux/fpc-iii.git] / arch / powerpc / xmon / xmon.c
blobb988b5addf864a581ff8c36e177379c32ba92518
1 /*
2 * Routines providing a simple monitor for use on the PowerMac.
4 * Copyright (C) 1996-2005 Paul Mackerras.
5 * Copyright (C) 2001 PPC64 Team, IBM Corp
6 * Copyrignt (C) 2006 Michael Ellerman, IBM Corp
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version
11 * 2 of the License, or (at your option) any later version.
13 #include <linux/errno.h>
14 #include <linux/sched.h>
15 #include <linux/smp.h>
16 #include <linux/mm.h>
17 #include <linux/reboot.h>
18 #include <linux/delay.h>
19 #include <linux/kallsyms.h>
20 #include <linux/kmsg_dump.h>
21 #include <linux/cpumask.h>
22 #include <linux/export.h>
23 #include <linux/sysrq.h>
24 #include <linux/interrupt.h>
25 #include <linux/irq.h>
26 #include <linux/bug.h>
27 #include <linux/nmi.h>
29 #include <asm/ptrace.h>
30 #include <asm/string.h>
31 #include <asm/prom.h>
32 #include <asm/machdep.h>
33 #include <asm/xmon.h>
34 #include <asm/processor.h>
35 #include <asm/pgtable.h>
36 #include <asm/mmu.h>
37 #include <asm/mmu_context.h>
38 #include <asm/cputable.h>
39 #include <asm/rtas.h>
40 #include <asm/sstep.h>
41 #include <asm/irq_regs.h>
42 #include <asm/spu.h>
43 #include <asm/spu_priv1.h>
44 #include <asm/setjmp.h>
45 #include <asm/reg.h>
46 #include <asm/debug.h>
47 #include <asm/hw_breakpoint.h>
49 #ifdef CONFIG_PPC64
50 #include <asm/hvcall.h>
51 #include <asm/paca.h>
52 #endif
54 #include "nonstdio.h"
55 #include "dis-asm.h"
57 #ifdef CONFIG_SMP
58 static cpumask_t cpus_in_xmon = CPU_MASK_NONE;
59 static unsigned long xmon_taken = 1;
60 static int xmon_owner;
61 static int xmon_gate;
62 #else
63 #define xmon_owner 0
64 #endif /* CONFIG_SMP */
66 static unsigned long in_xmon __read_mostly = 0;
68 static unsigned long adrs;
69 static int size = 1;
70 #define MAX_DUMP (128 * 1024)
71 static unsigned long ndump = 64;
72 static unsigned long nidump = 16;
73 static unsigned long ncsum = 4096;
74 static int termch;
75 static char tmpstr[128];
77 static long bus_error_jmp[JMP_BUF_LEN];
78 static int catch_memory_errors;
79 static long *xmon_fault_jmp[NR_CPUS];
81 /* Breakpoint stuff */
82 struct bpt {
83 unsigned long address;
84 unsigned int instr[2];
85 atomic_t ref_count;
86 int enabled;
87 unsigned long pad;
90 /* Bits in bpt.enabled */
91 #define BP_IABR_TE 1 /* IABR translation enabled */
92 #define BP_IABR 2
93 #define BP_TRAP 8
94 #define BP_DABR 0x10
96 #define NBPTS 256
97 static struct bpt bpts[NBPTS];
98 static struct bpt dabr;
99 static struct bpt *iabr;
100 static unsigned bpinstr = 0x7fe00008; /* trap */
102 #define BP_NUM(bp) ((bp) - bpts + 1)
104 /* Prototypes */
105 static int cmds(struct pt_regs *);
106 static int mread(unsigned long, void *, int);
107 static int mwrite(unsigned long, void *, int);
108 static int handle_fault(struct pt_regs *);
109 static void byterev(unsigned char *, int);
110 static void memex(void);
111 static int bsesc(void);
112 static void dump(void);
113 static void prdump(unsigned long, long);
114 static int ppc_inst_dump(unsigned long, long, int);
115 static void dump_log_buf(void);
116 static void backtrace(struct pt_regs *);
117 static void excprint(struct pt_regs *);
118 static void prregs(struct pt_regs *);
119 static void memops(int);
120 static void memlocate(void);
121 static void memzcan(void);
122 static void memdiffs(unsigned char *, unsigned char *, unsigned, unsigned);
123 int skipbl(void);
124 int scanhex(unsigned long *valp);
125 static void scannl(void);
126 static int hexdigit(int);
127 void getstring(char *, int);
128 static void flush_input(void);
129 static int inchar(void);
130 static void take_input(char *);
131 static unsigned long read_spr(int);
132 static void write_spr(int, unsigned long);
133 static void super_regs(void);
134 static void remove_bpts(void);
135 static void insert_bpts(void);
136 static void remove_cpu_bpts(void);
137 static void insert_cpu_bpts(void);
138 static struct bpt *at_breakpoint(unsigned long pc);
139 static struct bpt *in_breakpoint_table(unsigned long pc, unsigned long *offp);
140 static int do_step(struct pt_regs *);
141 static void bpt_cmds(void);
142 static void cacheflush(void);
143 static int cpu_cmd(void);
144 static void csum(void);
145 static void bootcmds(void);
146 static void proccall(void);
147 void dump_segments(void);
148 static void symbol_lookup(void);
149 static void xmon_show_stack(unsigned long sp, unsigned long lr,
150 unsigned long pc);
151 static void xmon_print_symbol(unsigned long address, const char *mid,
152 const char *after);
153 static const char *getvecname(unsigned long vec);
155 static int do_spu_cmd(void);
157 #ifdef CONFIG_44x
158 static void dump_tlb_44x(void);
159 #endif
160 #ifdef CONFIG_PPC_BOOK3E
161 static void dump_tlb_book3e(void);
162 #endif
164 static int xmon_no_auto_backtrace;
166 extern void xmon_enter(void);
167 extern void xmon_leave(void);
169 #ifdef CONFIG_PPC64
170 #define REG "%.16lx"
171 #else
172 #define REG "%.8lx"
173 #endif
175 #ifdef __LITTLE_ENDIAN__
176 #define GETWORD(v) (((v)[3] << 24) + ((v)[2] << 16) + ((v)[1] << 8) + (v)[0])
177 #else
178 #define GETWORD(v) (((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
179 #endif
181 #define isxdigit(c) (('0' <= (c) && (c) <= '9') \
182 || ('a' <= (c) && (c) <= 'f') \
183 || ('A' <= (c) && (c) <= 'F'))
184 #define isalnum(c) (('0' <= (c) && (c) <= '9') \
185 || ('a' <= (c) && (c) <= 'z') \
186 || ('A' <= (c) && (c) <= 'Z'))
187 #define isspace(c) (c == ' ' || c == '\t' || c == 10 || c == 13 || c == 0)
189 static char *help_string = "\
190 Commands:\n\
191 b show breakpoints\n\
192 bd set data breakpoint\n\
193 bi set instruction breakpoint\n\
194 bc clear breakpoint\n"
195 #ifdef CONFIG_SMP
197 c print cpus stopped in xmon\n\
198 c# try to switch to cpu number h (in hex)\n"
199 #endif
201 C checksum\n\
202 d dump bytes\n\
203 di dump instructions\n\
204 df dump float values\n\
205 dd dump double values\n\
206 dl dump the kernel log buffer\n"
207 #ifdef CONFIG_PPC64
209 dp[#] dump paca for current cpu, or cpu #\n\
210 dpa dump paca for all possible cpus\n"
211 #endif
213 dr dump stream of raw bytes\n\
214 e print exception information\n\
215 f flush cache\n\
216 la lookup symbol+offset of specified address\n\
217 ls lookup address of specified symbol\n\
218 m examine/change memory\n\
219 mm move a block of memory\n\
220 ms set a block of memory\n\
221 md compare two blocks of memory\n\
222 ml locate a block of memory\n\
223 mz zero a block of memory\n\
224 mi show information about memory allocation\n\
225 p call a procedure\n\
226 r print registers\n\
227 s single step\n"
228 #ifdef CONFIG_SPU_BASE
229 " ss stop execution on all spus\n\
230 sr restore execution on stopped spus\n\
231 sf # dump spu fields for spu # (in hex)\n\
232 sd # dump spu local store for spu # (in hex)\n\
233 sdi # disassemble spu local store for spu # (in hex)\n"
234 #endif
235 " S print special registers\n\
236 t print backtrace\n\
237 x exit monitor and recover\n\
238 X exit monitor and dont recover\n"
239 #if defined(CONFIG_PPC64) && !defined(CONFIG_PPC_BOOK3E)
240 " u dump segment table or SLB\n"
241 #elif defined(CONFIG_PPC_STD_MMU_32)
242 " u dump segment registers\n"
243 #elif defined(CONFIG_44x) || defined(CONFIG_PPC_BOOK3E)
244 " u dump TLB\n"
245 #endif
246 " ? help\n"
247 " zr reboot\n\
248 zh halt\n"
251 static struct pt_regs *xmon_regs;
253 static inline void sync(void)
255 asm volatile("sync; isync");
258 static inline void store_inst(void *p)
260 asm volatile ("dcbst 0,%0; sync; icbi 0,%0; isync" : : "r" (p));
263 static inline void cflush(void *p)
265 asm volatile ("dcbf 0,%0; icbi 0,%0" : : "r" (p));
268 static inline void cinval(void *p)
270 asm volatile ("dcbi 0,%0; icbi 0,%0" : : "r" (p));
274 * Disable surveillance (the service processor watchdog function)
275 * while we are in xmon.
276 * XXX we should re-enable it when we leave. :)
278 #define SURVEILLANCE_TOKEN 9000
280 static inline void disable_surveillance(void)
282 #ifdef CONFIG_PPC_PSERIES
283 /* Since this can't be a module, args should end up below 4GB. */
284 static struct rtas_args args;
287 * At this point we have got all the cpus we can into
288 * xmon, so there is hopefully no other cpu calling RTAS
289 * at the moment, even though we don't take rtas.lock.
290 * If we did try to take rtas.lock there would be a
291 * real possibility of deadlock.
293 args.token = rtas_token("set-indicator");
294 if (args.token == RTAS_UNKNOWN_SERVICE)
295 return;
296 args.nargs = 3;
297 args.nret = 1;
298 args.rets = &args.args[3];
299 args.args[0] = SURVEILLANCE_TOKEN;
300 args.args[1] = 0;
301 args.args[2] = 0;
302 enter_rtas(__pa(&args));
303 #endif /* CONFIG_PPC_PSERIES */
306 #ifdef CONFIG_SMP
307 static int xmon_speaker;
309 static void get_output_lock(void)
311 int me = smp_processor_id() + 0x100;
312 int last_speaker = 0, prev;
313 long timeout;
315 if (xmon_speaker == me)
316 return;
318 for (;;) {
319 last_speaker = cmpxchg(&xmon_speaker, 0, me);
320 if (last_speaker == 0)
321 return;
324 * Wait a full second for the lock, we might be on a slow
325 * console, but check every 100us.
327 timeout = 10000;
328 while (xmon_speaker == last_speaker) {
329 if (--timeout > 0) {
330 udelay(100);
331 continue;
334 /* hostile takeover */
335 prev = cmpxchg(&xmon_speaker, last_speaker, me);
336 if (prev == last_speaker)
337 return;
338 break;
343 static void release_output_lock(void)
345 xmon_speaker = 0;
348 int cpus_are_in_xmon(void)
350 return !cpumask_empty(&cpus_in_xmon);
352 #endif
354 static inline int unrecoverable_excp(struct pt_regs *regs)
356 #if defined(CONFIG_4xx) || defined(CONFIG_PPC_BOOK3E)
357 /* We have no MSR_RI bit on 4xx or Book3e, so we simply return false */
358 return 0;
359 #else
360 return ((regs->msr & MSR_RI) == 0);
361 #endif
364 static int xmon_core(struct pt_regs *regs, int fromipi)
366 int cmd = 0;
367 struct bpt *bp;
368 long recurse_jmp[JMP_BUF_LEN];
369 unsigned long offset;
370 unsigned long flags;
371 #ifdef CONFIG_SMP
372 int cpu;
373 int secondary;
374 unsigned long timeout;
375 #endif
377 local_irq_save(flags);
378 hard_irq_disable();
380 bp = in_breakpoint_table(regs->nip, &offset);
381 if (bp != NULL) {
382 regs->nip = bp->address + offset;
383 atomic_dec(&bp->ref_count);
386 remove_cpu_bpts();
388 #ifdef CONFIG_SMP
389 cpu = smp_processor_id();
390 if (cpumask_test_cpu(cpu, &cpus_in_xmon)) {
391 get_output_lock();
392 excprint(regs);
393 printf("cpu 0x%x: Exception %lx %s in xmon, "
394 "returning to main loop\n",
395 cpu, regs->trap, getvecname(TRAP(regs)));
396 release_output_lock();
397 longjmp(xmon_fault_jmp[cpu], 1);
400 if (setjmp(recurse_jmp) != 0) {
401 if (!in_xmon || !xmon_gate) {
402 get_output_lock();
403 printf("xmon: WARNING: bad recursive fault "
404 "on cpu 0x%x\n", cpu);
405 release_output_lock();
406 goto waiting;
408 secondary = !(xmon_taken && cpu == xmon_owner);
409 goto cmdloop;
412 xmon_fault_jmp[cpu] = recurse_jmp;
414 bp = NULL;
415 if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) == (MSR_IR|MSR_64BIT))
416 bp = at_breakpoint(regs->nip);
417 if (bp || unrecoverable_excp(regs))
418 fromipi = 0;
420 if (!fromipi) {
421 get_output_lock();
422 excprint(regs);
423 if (bp) {
424 printf("cpu 0x%x stopped at breakpoint 0x%lx (",
425 cpu, BP_NUM(bp));
426 xmon_print_symbol(regs->nip, " ", ")\n");
428 if (unrecoverable_excp(regs))
429 printf("WARNING: exception is not recoverable, "
430 "can't continue\n");
431 release_output_lock();
434 cpumask_set_cpu(cpu, &cpus_in_xmon);
436 waiting:
437 secondary = 1;
438 while (secondary && !xmon_gate) {
439 if (in_xmon == 0) {
440 if (fromipi)
441 goto leave;
442 secondary = test_and_set_bit(0, &in_xmon);
444 barrier();
447 if (!secondary && !xmon_gate) {
448 /* we are the first cpu to come in */
449 /* interrupt other cpu(s) */
450 int ncpus = num_online_cpus();
452 xmon_owner = cpu;
453 mb();
454 if (ncpus > 1) {
455 smp_send_debugger_break();
456 /* wait for other cpus to come in */
457 for (timeout = 100000000; timeout != 0; --timeout) {
458 if (cpumask_weight(&cpus_in_xmon) >= ncpus)
459 break;
460 barrier();
463 remove_bpts();
464 disable_surveillance();
465 /* for breakpoint or single step, print the current instr. */
466 if (bp || TRAP(regs) == 0xd00)
467 ppc_inst_dump(regs->nip, 1, 0);
468 printf("enter ? for help\n");
469 mb();
470 xmon_gate = 1;
471 barrier();
474 cmdloop:
475 while (in_xmon) {
476 if (secondary) {
477 if (cpu == xmon_owner) {
478 if (!test_and_set_bit(0, &xmon_taken)) {
479 secondary = 0;
480 continue;
482 /* missed it */
483 while (cpu == xmon_owner)
484 barrier();
486 barrier();
487 } else {
488 cmd = cmds(regs);
489 if (cmd != 0) {
490 /* exiting xmon */
491 insert_bpts();
492 xmon_gate = 0;
493 wmb();
494 in_xmon = 0;
495 break;
497 /* have switched to some other cpu */
498 secondary = 1;
501 leave:
502 cpumask_clear_cpu(cpu, &cpus_in_xmon);
503 xmon_fault_jmp[cpu] = NULL;
504 #else
505 /* UP is simple... */
506 if (in_xmon) {
507 printf("Exception %lx %s in xmon, returning to main loop\n",
508 regs->trap, getvecname(TRAP(regs)));
509 longjmp(xmon_fault_jmp[0], 1);
511 if (setjmp(recurse_jmp) == 0) {
512 xmon_fault_jmp[0] = recurse_jmp;
513 in_xmon = 1;
515 excprint(regs);
516 bp = at_breakpoint(regs->nip);
517 if (bp) {
518 printf("Stopped at breakpoint %lx (", BP_NUM(bp));
519 xmon_print_symbol(regs->nip, " ", ")\n");
521 if (unrecoverable_excp(regs))
522 printf("WARNING: exception is not recoverable, "
523 "can't continue\n");
524 remove_bpts();
525 disable_surveillance();
526 /* for breakpoint or single step, print the current instr. */
527 if (bp || TRAP(regs) == 0xd00)
528 ppc_inst_dump(regs->nip, 1, 0);
529 printf("enter ? for help\n");
532 cmd = cmds(regs);
534 insert_bpts();
535 in_xmon = 0;
536 #endif
538 #ifdef CONFIG_BOOKE
539 if (regs->msr & MSR_DE) {
540 bp = at_breakpoint(regs->nip);
541 if (bp != NULL) {
542 regs->nip = (unsigned long) &bp->instr[0];
543 atomic_inc(&bp->ref_count);
546 #else
547 if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) == (MSR_IR|MSR_64BIT)) {
548 bp = at_breakpoint(regs->nip);
549 if (bp != NULL) {
550 int stepped = emulate_step(regs, bp->instr[0]);
551 if (stepped == 0) {
552 regs->nip = (unsigned long) &bp->instr[0];
553 atomic_inc(&bp->ref_count);
554 } else if (stepped < 0) {
555 printf("Couldn't single-step %s instruction\n",
556 (IS_RFID(bp->instr[0])? "rfid": "mtmsrd"));
560 #endif
561 insert_cpu_bpts();
563 touch_nmi_watchdog();
564 local_irq_restore(flags);
566 return cmd != 'X' && cmd != EOF;
569 int xmon(struct pt_regs *excp)
571 struct pt_regs regs;
573 if (excp == NULL) {
574 ppc_save_regs(&regs);
575 excp = &regs;
578 return xmon_core(excp, 0);
580 EXPORT_SYMBOL(xmon);
582 irqreturn_t xmon_irq(int irq, void *d)
584 unsigned long flags;
585 local_irq_save(flags);
586 printf("Keyboard interrupt\n");
587 xmon(get_irq_regs());
588 local_irq_restore(flags);
589 return IRQ_HANDLED;
592 static int xmon_bpt(struct pt_regs *regs)
594 struct bpt *bp;
595 unsigned long offset;
597 if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) != (MSR_IR|MSR_64BIT))
598 return 0;
600 /* Are we at the trap at bp->instr[1] for some bp? */
601 bp = in_breakpoint_table(regs->nip, &offset);
602 if (bp != NULL && offset == 4) {
603 regs->nip = bp->address + 4;
604 atomic_dec(&bp->ref_count);
605 return 1;
608 /* Are we at a breakpoint? */
609 bp = at_breakpoint(regs->nip);
610 if (!bp)
611 return 0;
613 xmon_core(regs, 0);
615 return 1;
618 static int xmon_sstep(struct pt_regs *regs)
620 if (user_mode(regs))
621 return 0;
622 xmon_core(regs, 0);
623 return 1;
626 static int xmon_break_match(struct pt_regs *regs)
628 if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) != (MSR_IR|MSR_64BIT))
629 return 0;
630 if (dabr.enabled == 0)
631 return 0;
632 xmon_core(regs, 0);
633 return 1;
636 static int xmon_iabr_match(struct pt_regs *regs)
638 if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) != (MSR_IR|MSR_64BIT))
639 return 0;
640 if (iabr == NULL)
641 return 0;
642 xmon_core(regs, 0);
643 return 1;
646 static int xmon_ipi(struct pt_regs *regs)
648 #ifdef CONFIG_SMP
649 if (in_xmon && !cpumask_test_cpu(smp_processor_id(), &cpus_in_xmon))
650 xmon_core(regs, 1);
651 #endif
652 return 0;
655 static int xmon_fault_handler(struct pt_regs *regs)
657 struct bpt *bp;
658 unsigned long offset;
660 if (in_xmon && catch_memory_errors)
661 handle_fault(regs); /* doesn't return */
663 if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) == (MSR_IR|MSR_64BIT)) {
664 bp = in_breakpoint_table(regs->nip, &offset);
665 if (bp != NULL) {
666 regs->nip = bp->address + offset;
667 atomic_dec(&bp->ref_count);
671 return 0;
674 static struct bpt *at_breakpoint(unsigned long pc)
676 int i;
677 struct bpt *bp;
679 bp = bpts;
680 for (i = 0; i < NBPTS; ++i, ++bp)
681 if (bp->enabled && pc == bp->address)
682 return bp;
683 return NULL;
686 static struct bpt *in_breakpoint_table(unsigned long nip, unsigned long *offp)
688 unsigned long off;
690 off = nip - (unsigned long) bpts;
691 if (off >= sizeof(bpts))
692 return NULL;
693 off %= sizeof(struct bpt);
694 if (off != offsetof(struct bpt, instr[0])
695 && off != offsetof(struct bpt, instr[1]))
696 return NULL;
697 *offp = off - offsetof(struct bpt, instr[0]);
698 return (struct bpt *) (nip - off);
701 static struct bpt *new_breakpoint(unsigned long a)
703 struct bpt *bp;
705 a &= ~3UL;
706 bp = at_breakpoint(a);
707 if (bp)
708 return bp;
710 for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
711 if (!bp->enabled && atomic_read(&bp->ref_count) == 0) {
712 bp->address = a;
713 bp->instr[1] = bpinstr;
714 store_inst(&bp->instr[1]);
715 return bp;
719 printf("Sorry, no free breakpoints. Please clear one first.\n");
720 return NULL;
723 static void insert_bpts(void)
725 int i;
726 struct bpt *bp;
728 bp = bpts;
729 for (i = 0; i < NBPTS; ++i, ++bp) {
730 if ((bp->enabled & (BP_TRAP|BP_IABR)) == 0)
731 continue;
732 if (mread(bp->address, &bp->instr[0], 4) != 4) {
733 printf("Couldn't read instruction at %lx, "
734 "disabling breakpoint there\n", bp->address);
735 bp->enabled = 0;
736 continue;
738 if (IS_MTMSRD(bp->instr[0]) || IS_RFID(bp->instr[0])) {
739 printf("Breakpoint at %lx is on an mtmsrd or rfid "
740 "instruction, disabling it\n", bp->address);
741 bp->enabled = 0;
742 continue;
744 store_inst(&bp->instr[0]);
745 if (bp->enabled & BP_IABR)
746 continue;
747 if (mwrite(bp->address, &bpinstr, 4) != 4) {
748 printf("Couldn't write instruction at %lx, "
749 "disabling breakpoint there\n", bp->address);
750 bp->enabled &= ~BP_TRAP;
751 continue;
753 store_inst((void *)bp->address);
757 static void insert_cpu_bpts(void)
759 struct arch_hw_breakpoint brk;
761 if (dabr.enabled) {
762 brk.address = dabr.address;
763 brk.type = (dabr.enabled & HW_BRK_TYPE_DABR) | HW_BRK_TYPE_PRIV_ALL;
764 brk.len = 8;
765 __set_breakpoint(&brk);
767 if (iabr && cpu_has_feature(CPU_FTR_IABR))
768 mtspr(SPRN_IABR, iabr->address
769 | (iabr->enabled & (BP_IABR|BP_IABR_TE)));
772 static void remove_bpts(void)
774 int i;
775 struct bpt *bp;
776 unsigned instr;
778 bp = bpts;
779 for (i = 0; i < NBPTS; ++i, ++bp) {
780 if ((bp->enabled & (BP_TRAP|BP_IABR)) != BP_TRAP)
781 continue;
782 if (mread(bp->address, &instr, 4) == 4
783 && instr == bpinstr
784 && mwrite(bp->address, &bp->instr, 4) != 4)
785 printf("Couldn't remove breakpoint at %lx\n",
786 bp->address);
787 else
788 store_inst((void *)bp->address);
792 static void remove_cpu_bpts(void)
794 hw_breakpoint_disable();
795 if (cpu_has_feature(CPU_FTR_IABR))
796 mtspr(SPRN_IABR, 0);
799 /* Command interpreting routine */
800 static char *last_cmd;
802 static int
803 cmds(struct pt_regs *excp)
805 int cmd = 0;
807 last_cmd = NULL;
808 xmon_regs = excp;
810 if (!xmon_no_auto_backtrace) {
811 xmon_no_auto_backtrace = 1;
812 xmon_show_stack(excp->gpr[1], excp->link, excp->nip);
815 for(;;) {
816 #ifdef CONFIG_SMP
817 printf("%x:", smp_processor_id());
818 #endif /* CONFIG_SMP */
819 printf("mon> ");
820 flush_input();
821 termch = 0;
822 cmd = skipbl();
823 if( cmd == '\n' ) {
824 if (last_cmd == NULL)
825 continue;
826 take_input(last_cmd);
827 last_cmd = NULL;
828 cmd = inchar();
830 switch (cmd) {
831 case 'm':
832 cmd = inchar();
833 switch (cmd) {
834 case 'm':
835 case 's':
836 case 'd':
837 memops(cmd);
838 break;
839 case 'l':
840 memlocate();
841 break;
842 case 'z':
843 memzcan();
844 break;
845 case 'i':
846 show_mem(0);
847 break;
848 default:
849 termch = cmd;
850 memex();
852 break;
853 case 'd':
854 dump();
855 break;
856 case 'l':
857 symbol_lookup();
858 break;
859 case 'r':
860 prregs(excp); /* print regs */
861 break;
862 case 'e':
863 excprint(excp);
864 break;
865 case 'S':
866 super_regs();
867 break;
868 case 't':
869 backtrace(excp);
870 break;
871 case 'f':
872 cacheflush();
873 break;
874 case 's':
875 if (do_spu_cmd() == 0)
876 break;
877 if (do_step(excp))
878 return cmd;
879 break;
880 case 'x':
881 case 'X':
882 return cmd;
883 case EOF:
884 printf(" <no input ...>\n");
885 mdelay(2000);
886 return cmd;
887 case '?':
888 xmon_puts(help_string);
889 break;
890 case 'b':
891 bpt_cmds();
892 break;
893 case 'C':
894 csum();
895 break;
896 case 'c':
897 if (cpu_cmd())
898 return 0;
899 break;
900 case 'z':
901 bootcmds();
902 break;
903 case 'p':
904 proccall();
905 break;
906 #ifdef CONFIG_PPC_STD_MMU
907 case 'u':
908 dump_segments();
909 break;
910 #elif defined(CONFIG_4xx)
911 case 'u':
912 dump_tlb_44x();
913 break;
914 #elif defined(CONFIG_PPC_BOOK3E)
915 case 'u':
916 dump_tlb_book3e();
917 break;
918 #endif
919 default:
920 printf("Unrecognized command: ");
921 do {
922 if (' ' < cmd && cmd <= '~')
923 putchar(cmd);
924 else
925 printf("\\x%x", cmd);
926 cmd = inchar();
927 } while (cmd != '\n');
928 printf(" (type ? for help)\n");
929 break;
934 #ifdef CONFIG_BOOKE
935 static int do_step(struct pt_regs *regs)
937 regs->msr |= MSR_DE;
938 mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) | DBCR0_IC | DBCR0_IDM);
939 return 1;
941 #else
943 * Step a single instruction.
944 * Some instructions we emulate, others we execute with MSR_SE set.
946 static int do_step(struct pt_regs *regs)
948 unsigned int instr;
949 int stepped;
951 /* check we are in 64-bit kernel mode, translation enabled */
952 if ((regs->msr & (MSR_64BIT|MSR_PR|MSR_IR)) == (MSR_64BIT|MSR_IR)) {
953 if (mread(regs->nip, &instr, 4) == 4) {
954 stepped = emulate_step(regs, instr);
955 if (stepped < 0) {
956 printf("Couldn't single-step %s instruction\n",
957 (IS_RFID(instr)? "rfid": "mtmsrd"));
958 return 0;
960 if (stepped > 0) {
961 regs->trap = 0xd00 | (regs->trap & 1);
962 printf("stepped to ");
963 xmon_print_symbol(regs->nip, " ", "\n");
964 ppc_inst_dump(regs->nip, 1, 0);
965 return 0;
969 regs->msr |= MSR_SE;
970 return 1;
972 #endif
974 static void bootcmds(void)
976 int cmd;
978 cmd = inchar();
979 if (cmd == 'r')
980 ppc_md.restart(NULL);
981 else if (cmd == 'h')
982 ppc_md.halt();
983 else if (cmd == 'p')
984 ppc_md.power_off();
987 static int cpu_cmd(void)
989 #ifdef CONFIG_SMP
990 unsigned long cpu, first_cpu, last_cpu;
991 int timeout;
993 if (!scanhex(&cpu)) {
994 /* print cpus waiting or in xmon */
995 printf("cpus stopped:");
996 last_cpu = first_cpu = NR_CPUS;
997 for_each_possible_cpu(cpu) {
998 if (cpumask_test_cpu(cpu, &cpus_in_xmon)) {
999 if (cpu == last_cpu + 1) {
1000 last_cpu = cpu;
1001 } else {
1002 if (last_cpu != first_cpu)
1003 printf("-0x%lx", last_cpu);
1004 last_cpu = first_cpu = cpu;
1005 printf(" 0x%lx", cpu);
1009 if (last_cpu != first_cpu)
1010 printf("-0x%lx", last_cpu);
1011 printf("\n");
1012 return 0;
1014 /* try to switch to cpu specified */
1015 if (!cpumask_test_cpu(cpu, &cpus_in_xmon)) {
1016 printf("cpu 0x%x isn't in xmon\n", cpu);
1017 return 0;
1019 xmon_taken = 0;
1020 mb();
1021 xmon_owner = cpu;
1022 timeout = 10000000;
1023 while (!xmon_taken) {
1024 if (--timeout == 0) {
1025 if (test_and_set_bit(0, &xmon_taken))
1026 break;
1027 /* take control back */
1028 mb();
1029 xmon_owner = smp_processor_id();
1030 printf("cpu 0x%x didn't take control\n", cpu);
1031 return 0;
1033 barrier();
1035 return 1;
1036 #else
1037 return 0;
1038 #endif /* CONFIG_SMP */
1041 static unsigned short fcstab[256] = {
1042 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
1043 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
1044 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
1045 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
1046 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
1047 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
1048 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
1049 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
1050 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
1051 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
1052 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
1053 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
1054 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
1055 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
1056 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
1057 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
1058 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
1059 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
1060 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
1061 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
1062 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
1063 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
1064 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
1065 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
1066 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
1067 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
1068 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
1069 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
1070 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
1071 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
1072 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
1073 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
1076 #define FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
1078 static void
1079 csum(void)
1081 unsigned int i;
1082 unsigned short fcs;
1083 unsigned char v;
1085 if (!scanhex(&adrs))
1086 return;
1087 if (!scanhex(&ncsum))
1088 return;
1089 fcs = 0xffff;
1090 for (i = 0; i < ncsum; ++i) {
1091 if (mread(adrs+i, &v, 1) == 0) {
1092 printf("csum stopped at "REG"\n", adrs+i);
1093 break;
1095 fcs = FCS(fcs, v);
1097 printf("%x\n", fcs);
1101 * Check if this is a suitable place to put a breakpoint.
1103 static long check_bp_loc(unsigned long addr)
1105 unsigned int instr;
1107 addr &= ~3;
1108 if (!is_kernel_addr(addr)) {
1109 printf("Breakpoints may only be placed at kernel addresses\n");
1110 return 0;
1112 if (!mread(addr, &instr, sizeof(instr))) {
1113 printf("Can't read instruction at address %lx\n", addr);
1114 return 0;
1116 if (IS_MTMSRD(instr) || IS_RFID(instr)) {
1117 printf("Breakpoints may not be placed on mtmsrd or rfid "
1118 "instructions\n");
1119 return 0;
1121 return 1;
1124 static char *breakpoint_help_string =
1125 "Breakpoint command usage:\n"
1126 "b show breakpoints\n"
1127 "b <addr> [cnt] set breakpoint at given instr addr\n"
1128 "bc clear all breakpoints\n"
1129 "bc <n/addr> clear breakpoint number n or at addr\n"
1130 "bi <addr> [cnt] set hardware instr breakpoint (POWER3/RS64 only)\n"
1131 "bd <addr> [cnt] set hardware data breakpoint\n"
1134 static void
1135 bpt_cmds(void)
1137 int cmd;
1138 unsigned long a;
1139 int mode, i;
1140 struct bpt *bp;
1141 const char badaddr[] = "Only kernel addresses are permitted "
1142 "for breakpoints\n";
1144 cmd = inchar();
1145 switch (cmd) {
1146 #ifndef CONFIG_8xx
1147 case 'd': /* bd - hardware data breakpoint */
1148 mode = 7;
1149 cmd = inchar();
1150 if (cmd == 'r')
1151 mode = 5;
1152 else if (cmd == 'w')
1153 mode = 6;
1154 else
1155 termch = cmd;
1156 dabr.address = 0;
1157 dabr.enabled = 0;
1158 if (scanhex(&dabr.address)) {
1159 if (!is_kernel_addr(dabr.address)) {
1160 printf(badaddr);
1161 break;
1163 dabr.address &= ~HW_BRK_TYPE_DABR;
1164 dabr.enabled = mode | BP_DABR;
1166 break;
1168 case 'i': /* bi - hardware instr breakpoint */
1169 if (!cpu_has_feature(CPU_FTR_IABR)) {
1170 printf("Hardware instruction breakpoint "
1171 "not supported on this cpu\n");
1172 break;
1174 if (iabr) {
1175 iabr->enabled &= ~(BP_IABR | BP_IABR_TE);
1176 iabr = NULL;
1178 if (!scanhex(&a))
1179 break;
1180 if (!check_bp_loc(a))
1181 break;
1182 bp = new_breakpoint(a);
1183 if (bp != NULL) {
1184 bp->enabled |= BP_IABR | BP_IABR_TE;
1185 iabr = bp;
1187 break;
1188 #endif
1190 case 'c':
1191 if (!scanhex(&a)) {
1192 /* clear all breakpoints */
1193 for (i = 0; i < NBPTS; ++i)
1194 bpts[i].enabled = 0;
1195 iabr = NULL;
1196 dabr.enabled = 0;
1197 printf("All breakpoints cleared\n");
1198 break;
1201 if (a <= NBPTS && a >= 1) {
1202 /* assume a breakpoint number */
1203 bp = &bpts[a-1]; /* bp nums are 1 based */
1204 } else {
1205 /* assume a breakpoint address */
1206 bp = at_breakpoint(a);
1207 if (bp == NULL) {
1208 printf("No breakpoint at %lx\n", a);
1209 break;
1213 printf("Cleared breakpoint %lx (", BP_NUM(bp));
1214 xmon_print_symbol(bp->address, " ", ")\n");
1215 bp->enabled = 0;
1216 break;
1218 default:
1219 termch = cmd;
1220 cmd = skipbl();
1221 if (cmd == '?') {
1222 printf(breakpoint_help_string);
1223 break;
1225 termch = cmd;
1226 if (!scanhex(&a)) {
1227 /* print all breakpoints */
1228 printf(" type address\n");
1229 if (dabr.enabled) {
1230 printf(" data "REG" [", dabr.address);
1231 if (dabr.enabled & 1)
1232 printf("r");
1233 if (dabr.enabled & 2)
1234 printf("w");
1235 printf("]\n");
1237 for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
1238 if (!bp->enabled)
1239 continue;
1240 printf("%2x %s ", BP_NUM(bp),
1241 (bp->enabled & BP_IABR)? "inst": "trap");
1242 xmon_print_symbol(bp->address, " ", "\n");
1244 break;
1247 if (!check_bp_loc(a))
1248 break;
1249 bp = new_breakpoint(a);
1250 if (bp != NULL)
1251 bp->enabled |= BP_TRAP;
1252 break;
1256 /* Very cheap human name for vector lookup. */
1257 static
1258 const char *getvecname(unsigned long vec)
1260 char *ret;
1262 switch (vec) {
1263 case 0x100: ret = "(System Reset)"; break;
1264 case 0x200: ret = "(Machine Check)"; break;
1265 case 0x300: ret = "(Data Access)"; break;
1266 case 0x380: ret = "(Data SLB Access)"; break;
1267 case 0x400: ret = "(Instruction Access)"; break;
1268 case 0x480: ret = "(Instruction SLB Access)"; break;
1269 case 0x500: ret = "(Hardware Interrupt)"; break;
1270 case 0x600: ret = "(Alignment)"; break;
1271 case 0x700: ret = "(Program Check)"; break;
1272 case 0x800: ret = "(FPU Unavailable)"; break;
1273 case 0x900: ret = "(Decrementer)"; break;
1274 case 0x980: ret = "(Hypervisor Decrementer)"; break;
1275 case 0xa00: ret = "(Doorbell)"; break;
1276 case 0xc00: ret = "(System Call)"; break;
1277 case 0xd00: ret = "(Single Step)"; break;
1278 case 0xe40: ret = "(Emulation Assist)"; break;
1279 case 0xe60: ret = "(HMI)"; break;
1280 case 0xe80: ret = "(Hypervisor Doorbell)"; break;
1281 case 0xf00: ret = "(Performance Monitor)"; break;
1282 case 0xf20: ret = "(Altivec Unavailable)"; break;
1283 case 0x1300: ret = "(Instruction Breakpoint)"; break;
1284 case 0x1500: ret = "(Denormalisation)"; break;
1285 case 0x1700: ret = "(Altivec Assist)"; break;
1286 default: ret = "";
1288 return ret;
1291 static void get_function_bounds(unsigned long pc, unsigned long *startp,
1292 unsigned long *endp)
1294 unsigned long size, offset;
1295 const char *name;
1297 *startp = *endp = 0;
1298 if (pc == 0)
1299 return;
1300 if (setjmp(bus_error_jmp) == 0) {
1301 catch_memory_errors = 1;
1302 sync();
1303 name = kallsyms_lookup(pc, &size, &offset, NULL, tmpstr);
1304 if (name != NULL) {
1305 *startp = pc - offset;
1306 *endp = pc - offset + size;
1308 sync();
1310 catch_memory_errors = 0;
1313 #define LRSAVE_OFFSET (STACK_FRAME_LR_SAVE * sizeof(unsigned long))
1314 #define MARKER_OFFSET (STACK_FRAME_MARKER * sizeof(unsigned long))
1316 static void xmon_show_stack(unsigned long sp, unsigned long lr,
1317 unsigned long pc)
1319 int max_to_print = 64;
1320 unsigned long ip;
1321 unsigned long newsp;
1322 unsigned long marker;
1323 struct pt_regs regs;
1325 while (max_to_print--) {
1326 if (sp < PAGE_OFFSET) {
1327 if (sp != 0)
1328 printf("SP (%lx) is in userspace\n", sp);
1329 break;
1332 if (!mread(sp + LRSAVE_OFFSET, &ip, sizeof(unsigned long))
1333 || !mread(sp, &newsp, sizeof(unsigned long))) {
1334 printf("Couldn't read stack frame at %lx\n", sp);
1335 break;
1339 * For the first stack frame, try to work out if
1340 * LR and/or the saved LR value in the bottommost
1341 * stack frame are valid.
1343 if ((pc | lr) != 0) {
1344 unsigned long fnstart, fnend;
1345 unsigned long nextip;
1346 int printip = 1;
1348 get_function_bounds(pc, &fnstart, &fnend);
1349 nextip = 0;
1350 if (newsp > sp)
1351 mread(newsp + LRSAVE_OFFSET, &nextip,
1352 sizeof(unsigned long));
1353 if (lr == ip) {
1354 if (lr < PAGE_OFFSET
1355 || (fnstart <= lr && lr < fnend))
1356 printip = 0;
1357 } else if (lr == nextip) {
1358 printip = 0;
1359 } else if (lr >= PAGE_OFFSET
1360 && !(fnstart <= lr && lr < fnend)) {
1361 printf("[link register ] ");
1362 xmon_print_symbol(lr, " ", "\n");
1364 if (printip) {
1365 printf("["REG"] ", sp);
1366 xmon_print_symbol(ip, " ", " (unreliable)\n");
1368 pc = lr = 0;
1370 } else {
1371 printf("["REG"] ", sp);
1372 xmon_print_symbol(ip, " ", "\n");
1375 /* Look for "regshere" marker to see if this is
1376 an exception frame. */
1377 if (mread(sp + MARKER_OFFSET, &marker, sizeof(unsigned long))
1378 && marker == STACK_FRAME_REGS_MARKER) {
1379 if (mread(sp + STACK_FRAME_OVERHEAD, &regs, sizeof(regs))
1380 != sizeof(regs)) {
1381 printf("Couldn't read registers at %lx\n",
1382 sp + STACK_FRAME_OVERHEAD);
1383 break;
1385 printf("--- Exception: %lx %s at ", regs.trap,
1386 getvecname(TRAP(&regs)));
1387 pc = regs.nip;
1388 lr = regs.link;
1389 xmon_print_symbol(pc, " ", "\n");
1392 if (newsp == 0)
1393 break;
1395 sp = newsp;
1399 static void backtrace(struct pt_regs *excp)
1401 unsigned long sp;
1403 if (scanhex(&sp))
1404 xmon_show_stack(sp, 0, 0);
1405 else
1406 xmon_show_stack(excp->gpr[1], excp->link, excp->nip);
1407 scannl();
1410 static void print_bug_trap(struct pt_regs *regs)
1412 #ifdef CONFIG_BUG
1413 const struct bug_entry *bug;
1414 unsigned long addr;
1416 if (regs->msr & MSR_PR)
1417 return; /* not in kernel */
1418 addr = regs->nip; /* address of trap instruction */
1419 if (addr < PAGE_OFFSET)
1420 return;
1421 bug = find_bug(regs->nip);
1422 if (bug == NULL)
1423 return;
1424 if (is_warning_bug(bug))
1425 return;
1427 #ifdef CONFIG_DEBUG_BUGVERBOSE
1428 printf("kernel BUG at %s:%u!\n",
1429 bug->file, bug->line);
1430 #else
1431 printf("kernel BUG at %p!\n", (void *)bug->bug_addr);
1432 #endif
1433 #endif /* CONFIG_BUG */
1436 static void excprint(struct pt_regs *fp)
1438 unsigned long trap;
1440 #ifdef CONFIG_SMP
1441 printf("cpu 0x%x: ", smp_processor_id());
1442 #endif /* CONFIG_SMP */
1444 trap = TRAP(fp);
1445 printf("Vector: %lx %s at [%lx]\n", fp->trap, getvecname(trap), fp);
1446 printf(" pc: ");
1447 xmon_print_symbol(fp->nip, ": ", "\n");
1449 printf(" lr: ", fp->link);
1450 xmon_print_symbol(fp->link, ": ", "\n");
1452 printf(" sp: %lx\n", fp->gpr[1]);
1453 printf(" msr: %lx\n", fp->msr);
1455 if (trap == 0x300 || trap == 0x380 || trap == 0x600 || trap == 0x200) {
1456 printf(" dar: %lx\n", fp->dar);
1457 if (trap != 0x380)
1458 printf(" dsisr: %lx\n", fp->dsisr);
1461 printf(" current = 0x%lx\n", current);
1462 #ifdef CONFIG_PPC64
1463 printf(" paca = 0x%lx\t softe: %d\t irq_happened: 0x%02x\n",
1464 local_paca, local_paca->soft_enabled, local_paca->irq_happened);
1465 #endif
1466 if (current) {
1467 printf(" pid = %ld, comm = %s\n",
1468 current->pid, current->comm);
1471 if (trap == 0x700)
1472 print_bug_trap(fp);
1475 static void prregs(struct pt_regs *fp)
1477 int n, trap;
1478 unsigned long base;
1479 struct pt_regs regs;
1481 if (scanhex(&base)) {
1482 if (setjmp(bus_error_jmp) == 0) {
1483 catch_memory_errors = 1;
1484 sync();
1485 regs = *(struct pt_regs *)base;
1486 sync();
1487 __delay(200);
1488 } else {
1489 catch_memory_errors = 0;
1490 printf("*** Error reading registers from "REG"\n",
1491 base);
1492 return;
1494 catch_memory_errors = 0;
1495 fp = &regs;
1498 #ifdef CONFIG_PPC64
1499 if (FULL_REGS(fp)) {
1500 for (n = 0; n < 16; ++n)
1501 printf("R%.2ld = "REG" R%.2ld = "REG"\n",
1502 n, fp->gpr[n], n+16, fp->gpr[n+16]);
1503 } else {
1504 for (n = 0; n < 7; ++n)
1505 printf("R%.2ld = "REG" R%.2ld = "REG"\n",
1506 n, fp->gpr[n], n+7, fp->gpr[n+7]);
1508 #else
1509 for (n = 0; n < 32; ++n) {
1510 printf("R%.2d = %.8x%s", n, fp->gpr[n],
1511 (n & 3) == 3? "\n": " ");
1512 if (n == 12 && !FULL_REGS(fp)) {
1513 printf("\n");
1514 break;
1517 #endif
1518 printf("pc = ");
1519 xmon_print_symbol(fp->nip, " ", "\n");
1520 if (TRAP(fp) != 0xc00 && cpu_has_feature(CPU_FTR_CFAR)) {
1521 printf("cfar= ");
1522 xmon_print_symbol(fp->orig_gpr3, " ", "\n");
1524 printf("lr = ");
1525 xmon_print_symbol(fp->link, " ", "\n");
1526 printf("msr = "REG" cr = %.8lx\n", fp->msr, fp->ccr);
1527 printf("ctr = "REG" xer = "REG" trap = %4lx\n",
1528 fp->ctr, fp->xer, fp->trap);
1529 trap = TRAP(fp);
1530 if (trap == 0x300 || trap == 0x380 || trap == 0x600)
1531 printf("dar = "REG" dsisr = %.8lx\n", fp->dar, fp->dsisr);
1534 static void cacheflush(void)
1536 int cmd;
1537 unsigned long nflush;
1539 cmd = inchar();
1540 if (cmd != 'i')
1541 termch = cmd;
1542 scanhex((void *)&adrs);
1543 if (termch != '\n')
1544 termch = 0;
1545 nflush = 1;
1546 scanhex(&nflush);
1547 nflush = (nflush + L1_CACHE_BYTES - 1) / L1_CACHE_BYTES;
1548 if (setjmp(bus_error_jmp) == 0) {
1549 catch_memory_errors = 1;
1550 sync();
1552 if (cmd != 'i') {
1553 for (; nflush > 0; --nflush, adrs += L1_CACHE_BYTES)
1554 cflush((void *) adrs);
1555 } else {
1556 for (; nflush > 0; --nflush, adrs += L1_CACHE_BYTES)
1557 cinval((void *) adrs);
1559 sync();
1560 /* wait a little while to see if we get a machine check */
1561 __delay(200);
1563 catch_memory_errors = 0;
1566 static unsigned long
1567 read_spr(int n)
1569 unsigned int instrs[2];
1570 unsigned long (*code)(void);
1571 unsigned long ret = -1UL;
1572 #ifdef CONFIG_PPC64
1573 unsigned long opd[3];
1575 opd[0] = (unsigned long)instrs;
1576 opd[1] = 0;
1577 opd[2] = 0;
1578 code = (unsigned long (*)(void)) opd;
1579 #else
1580 code = (unsigned long (*)(void)) instrs;
1581 #endif
1583 /* mfspr r3,n; blr */
1584 instrs[0] = 0x7c6002a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
1585 instrs[1] = 0x4e800020;
1586 store_inst(instrs);
1587 store_inst(instrs+1);
1589 if (setjmp(bus_error_jmp) == 0) {
1590 catch_memory_errors = 1;
1591 sync();
1593 ret = code();
1595 sync();
1596 /* wait a little while to see if we get a machine check */
1597 __delay(200);
1598 n = size;
1601 return ret;
1604 static void
1605 write_spr(int n, unsigned long val)
1607 unsigned int instrs[2];
1608 unsigned long (*code)(unsigned long);
1609 #ifdef CONFIG_PPC64
1610 unsigned long opd[3];
1612 opd[0] = (unsigned long)instrs;
1613 opd[1] = 0;
1614 opd[2] = 0;
1615 code = (unsigned long (*)(unsigned long)) opd;
1616 #else
1617 code = (unsigned long (*)(unsigned long)) instrs;
1618 #endif
1620 instrs[0] = 0x7c6003a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
1621 instrs[1] = 0x4e800020;
1622 store_inst(instrs);
1623 store_inst(instrs+1);
1625 if (setjmp(bus_error_jmp) == 0) {
1626 catch_memory_errors = 1;
1627 sync();
1629 code(val);
1631 sync();
1632 /* wait a little while to see if we get a machine check */
1633 __delay(200);
1634 n = size;
1638 static unsigned long regno;
1639 extern char exc_prolog;
1640 extern char dec_exc;
1642 static void super_regs(void)
1644 int cmd;
1645 unsigned long val;
1647 cmd = skipbl();
1648 if (cmd == '\n') {
1649 unsigned long sp, toc;
1650 asm("mr %0,1" : "=r" (sp) :);
1651 asm("mr %0,2" : "=r" (toc) :);
1653 printf("msr = "REG" sprg0= "REG"\n",
1654 mfmsr(), mfspr(SPRN_SPRG0));
1655 printf("pvr = "REG" sprg1= "REG"\n",
1656 mfspr(SPRN_PVR), mfspr(SPRN_SPRG1));
1657 printf("dec = "REG" sprg2= "REG"\n",
1658 mfspr(SPRN_DEC), mfspr(SPRN_SPRG2));
1659 printf("sp = "REG" sprg3= "REG"\n", sp, mfspr(SPRN_SPRG3));
1660 printf("toc = "REG" dar = "REG"\n", toc, mfspr(SPRN_DAR));
1662 return;
1665 scanhex(&regno);
1666 switch (cmd) {
1667 case 'w':
1668 val = read_spr(regno);
1669 scanhex(&val);
1670 write_spr(regno, val);
1671 /* fall through */
1672 case 'r':
1673 printf("spr %lx = %lx\n", regno, read_spr(regno));
1674 break;
1676 scannl();
1680 * Stuff for reading and writing memory safely
1682 static int
1683 mread(unsigned long adrs, void *buf, int size)
1685 volatile int n;
1686 char *p, *q;
1688 n = 0;
1689 if (setjmp(bus_error_jmp) == 0) {
1690 catch_memory_errors = 1;
1691 sync();
1692 p = (char *)adrs;
1693 q = (char *)buf;
1694 switch (size) {
1695 case 2:
1696 *(u16 *)q = *(u16 *)p;
1697 break;
1698 case 4:
1699 *(u32 *)q = *(u32 *)p;
1700 break;
1701 case 8:
1702 *(u64 *)q = *(u64 *)p;
1703 break;
1704 default:
1705 for( ; n < size; ++n) {
1706 *q++ = *p++;
1707 sync();
1710 sync();
1711 /* wait a little while to see if we get a machine check */
1712 __delay(200);
1713 n = size;
1715 catch_memory_errors = 0;
1716 return n;
1719 static int
1720 mwrite(unsigned long adrs, void *buf, int size)
1722 volatile int n;
1723 char *p, *q;
1725 n = 0;
1726 if (setjmp(bus_error_jmp) == 0) {
1727 catch_memory_errors = 1;
1728 sync();
1729 p = (char *) adrs;
1730 q = (char *) buf;
1731 switch (size) {
1732 case 2:
1733 *(u16 *)p = *(u16 *)q;
1734 break;
1735 case 4:
1736 *(u32 *)p = *(u32 *)q;
1737 break;
1738 case 8:
1739 *(u64 *)p = *(u64 *)q;
1740 break;
1741 default:
1742 for ( ; n < size; ++n) {
1743 *p++ = *q++;
1744 sync();
1747 sync();
1748 /* wait a little while to see if we get a machine check */
1749 __delay(200);
1750 n = size;
1751 } else {
1752 printf("*** Error writing address "REG"\n", adrs + n);
1754 catch_memory_errors = 0;
1755 return n;
1758 static int fault_type;
1759 static int fault_except;
1760 static char *fault_chars[] = { "--", "**", "##" };
1762 static int handle_fault(struct pt_regs *regs)
1764 fault_except = TRAP(regs);
1765 switch (TRAP(regs)) {
1766 case 0x200:
1767 fault_type = 0;
1768 break;
1769 case 0x300:
1770 case 0x380:
1771 fault_type = 1;
1772 break;
1773 default:
1774 fault_type = 2;
1777 longjmp(bus_error_jmp, 1);
1779 return 0;
1782 #define SWAP(a, b, t) ((t) = (a), (a) = (b), (b) = (t))
1784 static void
1785 byterev(unsigned char *val, int size)
1787 int t;
1789 switch (size) {
1790 case 2:
1791 SWAP(val[0], val[1], t);
1792 break;
1793 case 4:
1794 SWAP(val[0], val[3], t);
1795 SWAP(val[1], val[2], t);
1796 break;
1797 case 8: /* is there really any use for this? */
1798 SWAP(val[0], val[7], t);
1799 SWAP(val[1], val[6], t);
1800 SWAP(val[2], val[5], t);
1801 SWAP(val[3], val[4], t);
1802 break;
1806 static int brev;
1807 static int mnoread;
1809 static char *memex_help_string =
1810 "Memory examine command usage:\n"
1811 "m [addr] [flags] examine/change memory\n"
1812 " addr is optional. will start where left off.\n"
1813 " flags may include chars from this set:\n"
1814 " b modify by bytes (default)\n"
1815 " w modify by words (2 byte)\n"
1816 " l modify by longs (4 byte)\n"
1817 " d modify by doubleword (8 byte)\n"
1818 " r toggle reverse byte order mode\n"
1819 " n do not read memory (for i/o spaces)\n"
1820 " . ok to read (default)\n"
1821 "NOTE: flags are saved as defaults\n"
1824 static char *memex_subcmd_help_string =
1825 "Memory examine subcommands:\n"
1826 " hexval write this val to current location\n"
1827 " 'string' write chars from string to this location\n"
1828 " ' increment address\n"
1829 " ^ decrement address\n"
1830 " / increment addr by 0x10. //=0x100, ///=0x1000, etc\n"
1831 " \\ decrement addr by 0x10. \\\\=0x100, \\\\\\=0x1000, etc\n"
1832 " ` clear no-read flag\n"
1833 " ; stay at this addr\n"
1834 " v change to byte mode\n"
1835 " w change to word (2 byte) mode\n"
1836 " l change to long (4 byte) mode\n"
1837 " u change to doubleword (8 byte) mode\n"
1838 " m addr change current addr\n"
1839 " n toggle no-read flag\n"
1840 " r toggle byte reverse flag\n"
1841 " < count back up count bytes\n"
1842 " > count skip forward count bytes\n"
1843 " x exit this mode\n"
1846 static void
1847 memex(void)
1849 int cmd, inc, i, nslash;
1850 unsigned long n;
1851 unsigned char val[16];
1853 scanhex((void *)&adrs);
1854 cmd = skipbl();
1855 if (cmd == '?') {
1856 printf(memex_help_string);
1857 return;
1858 } else {
1859 termch = cmd;
1861 last_cmd = "m\n";
1862 while ((cmd = skipbl()) != '\n') {
1863 switch( cmd ){
1864 case 'b': size = 1; break;
1865 case 'w': size = 2; break;
1866 case 'l': size = 4; break;
1867 case 'd': size = 8; break;
1868 case 'r': brev = !brev; break;
1869 case 'n': mnoread = 1; break;
1870 case '.': mnoread = 0; break;
1873 if( size <= 0 )
1874 size = 1;
1875 else if( size > 8 )
1876 size = 8;
1877 for(;;){
1878 if (!mnoread)
1879 n = mread(adrs, val, size);
1880 printf(REG"%c", adrs, brev? 'r': ' ');
1881 if (!mnoread) {
1882 if (brev)
1883 byterev(val, size);
1884 putchar(' ');
1885 for (i = 0; i < n; ++i)
1886 printf("%.2x", val[i]);
1887 for (; i < size; ++i)
1888 printf("%s", fault_chars[fault_type]);
1890 putchar(' ');
1891 inc = size;
1892 nslash = 0;
1893 for(;;){
1894 if( scanhex(&n) ){
1895 for (i = 0; i < size; ++i)
1896 val[i] = n >> (i * 8);
1897 if (!brev)
1898 byterev(val, size);
1899 mwrite(adrs, val, size);
1900 inc = size;
1902 cmd = skipbl();
1903 if (cmd == '\n')
1904 break;
1905 inc = 0;
1906 switch (cmd) {
1907 case '\'':
1908 for(;;){
1909 n = inchar();
1910 if( n == '\\' )
1911 n = bsesc();
1912 else if( n == '\'' )
1913 break;
1914 for (i = 0; i < size; ++i)
1915 val[i] = n >> (i * 8);
1916 if (!brev)
1917 byterev(val, size);
1918 mwrite(adrs, val, size);
1919 adrs += size;
1921 adrs -= size;
1922 inc = size;
1923 break;
1924 case ',':
1925 adrs += size;
1926 break;
1927 case '.':
1928 mnoread = 0;
1929 break;
1930 case ';':
1931 break;
1932 case 'x':
1933 case EOF:
1934 scannl();
1935 return;
1936 case 'b':
1937 case 'v':
1938 size = 1;
1939 break;
1940 case 'w':
1941 size = 2;
1942 break;
1943 case 'l':
1944 size = 4;
1945 break;
1946 case 'u':
1947 size = 8;
1948 break;
1949 case '^':
1950 adrs -= size;
1951 break;
1952 break;
1953 case '/':
1954 if (nslash > 0)
1955 adrs -= 1 << nslash;
1956 else
1957 nslash = 0;
1958 nslash += 4;
1959 adrs += 1 << nslash;
1960 break;
1961 case '\\':
1962 if (nslash < 0)
1963 adrs += 1 << -nslash;
1964 else
1965 nslash = 0;
1966 nslash -= 4;
1967 adrs -= 1 << -nslash;
1968 break;
1969 case 'm':
1970 scanhex((void *)&adrs);
1971 break;
1972 case 'n':
1973 mnoread = 1;
1974 break;
1975 case 'r':
1976 brev = !brev;
1977 break;
1978 case '<':
1979 n = size;
1980 scanhex(&n);
1981 adrs -= n;
1982 break;
1983 case '>':
1984 n = size;
1985 scanhex(&n);
1986 adrs += n;
1987 break;
1988 case '?':
1989 printf(memex_subcmd_help_string);
1990 break;
1993 adrs += inc;
1997 static int
1998 bsesc(void)
2000 int c;
2002 c = inchar();
2003 switch( c ){
2004 case 'n': c = '\n'; break;
2005 case 'r': c = '\r'; break;
2006 case 'b': c = '\b'; break;
2007 case 't': c = '\t'; break;
2009 return c;
2012 static void xmon_rawdump (unsigned long adrs, long ndump)
2014 long n, m, r, nr;
2015 unsigned char temp[16];
2017 for (n = ndump; n > 0;) {
2018 r = n < 16? n: 16;
2019 nr = mread(adrs, temp, r);
2020 adrs += nr;
2021 for (m = 0; m < r; ++m) {
2022 if (m < nr)
2023 printf("%.2x", temp[m]);
2024 else
2025 printf("%s", fault_chars[fault_type]);
2027 n -= r;
2028 if (nr < r)
2029 break;
2031 printf("\n");
2034 #ifdef CONFIG_PPC64
2035 static void dump_one_paca(int cpu)
2037 struct paca_struct *p;
2039 if (setjmp(bus_error_jmp) != 0) {
2040 printf("*** Error dumping paca for cpu 0x%x!\n", cpu);
2041 return;
2044 catch_memory_errors = 1;
2045 sync();
2047 p = &paca[cpu];
2049 printf("paca for cpu 0x%x @ %p:\n", cpu, p);
2051 printf(" %-*s = %s\n", 16, "possible", cpu_possible(cpu) ? "yes" : "no");
2052 printf(" %-*s = %s\n", 16, "present", cpu_present(cpu) ? "yes" : "no");
2053 printf(" %-*s = %s\n", 16, "online", cpu_online(cpu) ? "yes" : "no");
2055 #define DUMP(paca, name, format) \
2056 printf(" %-*s = %#-*"format"\t(0x%lx)\n", 16, #name, 18, paca->name, \
2057 offsetof(struct paca_struct, name));
2059 DUMP(p, lock_token, "x");
2060 DUMP(p, paca_index, "x");
2061 DUMP(p, kernel_toc, "lx");
2062 DUMP(p, kernelbase, "lx");
2063 DUMP(p, kernel_msr, "lx");
2064 DUMP(p, emergency_sp, "p");
2065 #ifdef CONFIG_PPC_BOOK3S_64
2066 DUMP(p, mc_emergency_sp, "p");
2067 DUMP(p, in_mce, "x");
2068 #endif
2069 DUMP(p, data_offset, "lx");
2070 DUMP(p, hw_cpu_id, "x");
2071 DUMP(p, cpu_start, "x");
2072 DUMP(p, kexec_state, "x");
2073 DUMP(p, __current, "p");
2074 DUMP(p, kstack, "lx");
2075 DUMP(p, stab_rr, "lx");
2076 DUMP(p, saved_r1, "lx");
2077 DUMP(p, trap_save, "x");
2078 DUMP(p, soft_enabled, "x");
2079 DUMP(p, irq_happened, "x");
2080 DUMP(p, io_sync, "x");
2081 DUMP(p, irq_work_pending, "x");
2082 DUMP(p, nap_state_lost, "x");
2084 #undef DUMP
2086 catch_memory_errors = 0;
2087 sync();
2090 static void dump_all_pacas(void)
2092 int cpu;
2094 if (num_possible_cpus() == 0) {
2095 printf("No possible cpus, use 'dp #' to dump individual cpus\n");
2096 return;
2099 for_each_possible_cpu(cpu)
2100 dump_one_paca(cpu);
2103 static void dump_pacas(void)
2105 unsigned long num;
2106 int c;
2108 c = inchar();
2109 if (c == 'a') {
2110 dump_all_pacas();
2111 return;
2114 termch = c; /* Put c back, it wasn't 'a' */
2116 if (scanhex(&num))
2117 dump_one_paca(num);
2118 else
2119 dump_one_paca(xmon_owner);
2121 #endif
2123 #define isxdigit(c) (('0' <= (c) && (c) <= '9') \
2124 || ('a' <= (c) && (c) <= 'f') \
2125 || ('A' <= (c) && (c) <= 'F'))
2126 static void
2127 dump(void)
2129 int c;
2131 c = inchar();
2133 #ifdef CONFIG_PPC64
2134 if (c == 'p') {
2135 dump_pacas();
2136 return;
2138 #endif
2140 if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')
2141 termch = c;
2142 scanhex((void *)&adrs);
2143 if (termch != '\n')
2144 termch = 0;
2145 if (c == 'i') {
2146 scanhex(&nidump);
2147 if (nidump == 0)
2148 nidump = 16;
2149 else if (nidump > MAX_DUMP)
2150 nidump = MAX_DUMP;
2151 adrs += ppc_inst_dump(adrs, nidump, 1);
2152 last_cmd = "di\n";
2153 } else if (c == 'l') {
2154 dump_log_buf();
2155 } else if (c == 'r') {
2156 scanhex(&ndump);
2157 if (ndump == 0)
2158 ndump = 64;
2159 xmon_rawdump(adrs, ndump);
2160 adrs += ndump;
2161 last_cmd = "dr\n";
2162 } else {
2163 scanhex(&ndump);
2164 if (ndump == 0)
2165 ndump = 64;
2166 else if (ndump > MAX_DUMP)
2167 ndump = MAX_DUMP;
2168 prdump(adrs, ndump);
2169 adrs += ndump;
2170 last_cmd = "d\n";
2174 static void
2175 prdump(unsigned long adrs, long ndump)
2177 long n, m, c, r, nr;
2178 unsigned char temp[16];
2180 for (n = ndump; n > 0;) {
2181 printf(REG, adrs);
2182 putchar(' ');
2183 r = n < 16? n: 16;
2184 nr = mread(adrs, temp, r);
2185 adrs += nr;
2186 for (m = 0; m < r; ++m) {
2187 if ((m & (sizeof(long) - 1)) == 0 && m > 0)
2188 putchar(' ');
2189 if (m < nr)
2190 printf("%.2x", temp[m]);
2191 else
2192 printf("%s", fault_chars[fault_type]);
2194 for (; m < 16; ++m) {
2195 if ((m & (sizeof(long) - 1)) == 0)
2196 putchar(' ');
2197 printf(" ");
2199 printf(" |");
2200 for (m = 0; m < r; ++m) {
2201 if (m < nr) {
2202 c = temp[m];
2203 putchar(' ' <= c && c <= '~'? c: '.');
2204 } else
2205 putchar(' ');
2207 n -= r;
2208 for (; m < 16; ++m)
2209 putchar(' ');
2210 printf("|\n");
2211 if (nr < r)
2212 break;
2216 typedef int (*instruction_dump_func)(unsigned long inst, unsigned long addr);
2218 static int
2219 generic_inst_dump(unsigned long adr, long count, int praddr,
2220 instruction_dump_func dump_func)
2222 int nr, dotted;
2223 unsigned long first_adr;
2224 unsigned long inst, last_inst = 0;
2225 unsigned char val[4];
2227 dotted = 0;
2228 for (first_adr = adr; count > 0; --count, adr += 4) {
2229 nr = mread(adr, val, 4);
2230 if (nr == 0) {
2231 if (praddr) {
2232 const char *x = fault_chars[fault_type];
2233 printf(REG" %s%s%s%s\n", adr, x, x, x, x);
2235 break;
2237 inst = GETWORD(val);
2238 if (adr > first_adr && inst == last_inst) {
2239 if (!dotted) {
2240 printf(" ...\n");
2241 dotted = 1;
2243 continue;
2245 dotted = 0;
2246 last_inst = inst;
2247 if (praddr)
2248 printf(REG" %.8x", adr, inst);
2249 printf("\t");
2250 dump_func(inst, adr);
2251 printf("\n");
2253 return adr - first_adr;
2256 static int
2257 ppc_inst_dump(unsigned long adr, long count, int praddr)
2259 return generic_inst_dump(adr, count, praddr, print_insn_powerpc);
2262 void
2263 print_address(unsigned long addr)
2265 xmon_print_symbol(addr, "\t# ", "");
2268 void
2269 dump_log_buf(void)
2271 struct kmsg_dumper dumper = { .active = 1 };
2272 unsigned char buf[128];
2273 size_t len;
2275 if (setjmp(bus_error_jmp) != 0) {
2276 printf("Error dumping printk buffer!\n");
2277 return;
2280 catch_memory_errors = 1;
2281 sync();
2283 kmsg_dump_rewind_nolock(&dumper);
2284 while (kmsg_dump_get_line_nolock(&dumper, false, buf, sizeof(buf), &len)) {
2285 buf[len] = '\0';
2286 printf("%s", buf);
2289 sync();
2290 /* wait a little while to see if we get a machine check */
2291 __delay(200);
2292 catch_memory_errors = 0;
2296 * Memory operations - move, set, print differences
2298 static unsigned long mdest; /* destination address */
2299 static unsigned long msrc; /* source address */
2300 static unsigned long mval; /* byte value to set memory to */
2301 static unsigned long mcount; /* # bytes to affect */
2302 static unsigned long mdiffs; /* max # differences to print */
2304 static void
2305 memops(int cmd)
2307 scanhex((void *)&mdest);
2308 if( termch != '\n' )
2309 termch = 0;
2310 scanhex((void *)(cmd == 's'? &mval: &msrc));
2311 if( termch != '\n' )
2312 termch = 0;
2313 scanhex((void *)&mcount);
2314 switch( cmd ){
2315 case 'm':
2316 memmove((void *)mdest, (void *)msrc, mcount);
2317 break;
2318 case 's':
2319 memset((void *)mdest, mval, mcount);
2320 break;
2321 case 'd':
2322 if( termch != '\n' )
2323 termch = 0;
2324 scanhex((void *)&mdiffs);
2325 memdiffs((unsigned char *)mdest, (unsigned char *)msrc, mcount, mdiffs);
2326 break;
2330 static void
2331 memdiffs(unsigned char *p1, unsigned char *p2, unsigned nb, unsigned maxpr)
2333 unsigned n, prt;
2335 prt = 0;
2336 for( n = nb; n > 0; --n )
2337 if( *p1++ != *p2++ )
2338 if( ++prt <= maxpr )
2339 printf("%.16x %.2x # %.16x %.2x\n", p1 - 1,
2340 p1[-1], p2 - 1, p2[-1]);
2341 if( prt > maxpr )
2342 printf("Total of %d differences\n", prt);
2345 static unsigned mend;
2346 static unsigned mask;
2348 static void
2349 memlocate(void)
2351 unsigned a, n;
2352 unsigned char val[4];
2354 last_cmd = "ml";
2355 scanhex((void *)&mdest);
2356 if (termch != '\n') {
2357 termch = 0;
2358 scanhex((void *)&mend);
2359 if (termch != '\n') {
2360 termch = 0;
2361 scanhex((void *)&mval);
2362 mask = ~0;
2363 if (termch != '\n') termch = 0;
2364 scanhex((void *)&mask);
2367 n = 0;
2368 for (a = mdest; a < mend; a += 4) {
2369 if (mread(a, val, 4) == 4
2370 && ((GETWORD(val) ^ mval) & mask) == 0) {
2371 printf("%.16x: %.16x\n", a, GETWORD(val));
2372 if (++n >= 10)
2373 break;
2378 static unsigned long mskip = 0x1000;
2379 static unsigned long mlim = 0xffffffff;
2381 static void
2382 memzcan(void)
2384 unsigned char v;
2385 unsigned a;
2386 int ok, ook;
2388 scanhex(&mdest);
2389 if (termch != '\n') termch = 0;
2390 scanhex(&mskip);
2391 if (termch != '\n') termch = 0;
2392 scanhex(&mlim);
2393 ook = 0;
2394 for (a = mdest; a < mlim; a += mskip) {
2395 ok = mread(a, &v, 1);
2396 if (ok && !ook) {
2397 printf("%.8x .. ", a);
2398 } else if (!ok && ook)
2399 printf("%.8x\n", a - mskip);
2400 ook = ok;
2401 if (a + mskip < a)
2402 break;
2404 if (ook)
2405 printf("%.8x\n", a - mskip);
2408 static void proccall(void)
2410 unsigned long args[8];
2411 unsigned long ret;
2412 int i;
2413 typedef unsigned long (*callfunc_t)(unsigned long, unsigned long,
2414 unsigned long, unsigned long, unsigned long,
2415 unsigned long, unsigned long, unsigned long);
2416 callfunc_t func;
2418 if (!scanhex(&adrs))
2419 return;
2420 if (termch != '\n')
2421 termch = 0;
2422 for (i = 0; i < 8; ++i)
2423 args[i] = 0;
2424 for (i = 0; i < 8; ++i) {
2425 if (!scanhex(&args[i]) || termch == '\n')
2426 break;
2427 termch = 0;
2429 func = (callfunc_t) adrs;
2430 ret = 0;
2431 if (setjmp(bus_error_jmp) == 0) {
2432 catch_memory_errors = 1;
2433 sync();
2434 ret = func(args[0], args[1], args[2], args[3],
2435 args[4], args[5], args[6], args[7]);
2436 sync();
2437 printf("return value is 0x%lx\n", ret);
2438 } else {
2439 printf("*** %x exception occurred\n", fault_except);
2441 catch_memory_errors = 0;
2444 /* Input scanning routines */
2446 skipbl(void)
2448 int c;
2450 if( termch != 0 ){
2451 c = termch;
2452 termch = 0;
2453 } else
2454 c = inchar();
2455 while( c == ' ' || c == '\t' )
2456 c = inchar();
2457 return c;
2460 #define N_PTREGS 44
2461 static char *regnames[N_PTREGS] = {
2462 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
2463 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
2464 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
2465 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
2466 "pc", "msr", "or3", "ctr", "lr", "xer", "ccr",
2467 #ifdef CONFIG_PPC64
2468 "softe",
2469 #else
2470 "mq",
2471 #endif
2472 "trap", "dar", "dsisr", "res"
2476 scanhex(unsigned long *vp)
2478 int c, d;
2479 unsigned long v;
2481 c = skipbl();
2482 if (c == '%') {
2483 /* parse register name */
2484 char regname[8];
2485 int i;
2487 for (i = 0; i < sizeof(regname) - 1; ++i) {
2488 c = inchar();
2489 if (!isalnum(c)) {
2490 termch = c;
2491 break;
2493 regname[i] = c;
2495 regname[i] = 0;
2496 for (i = 0; i < N_PTREGS; ++i) {
2497 if (strcmp(regnames[i], regname) == 0) {
2498 if (xmon_regs == NULL) {
2499 printf("regs not available\n");
2500 return 0;
2502 *vp = ((unsigned long *)xmon_regs)[i];
2503 return 1;
2506 printf("invalid register name '%%%s'\n", regname);
2507 return 0;
2510 /* skip leading "0x" if any */
2512 if (c == '0') {
2513 c = inchar();
2514 if (c == 'x') {
2515 c = inchar();
2516 } else {
2517 d = hexdigit(c);
2518 if (d == EOF) {
2519 termch = c;
2520 *vp = 0;
2521 return 1;
2524 } else if (c == '$') {
2525 int i;
2526 for (i=0; i<63; i++) {
2527 c = inchar();
2528 if (isspace(c)) {
2529 termch = c;
2530 break;
2532 tmpstr[i] = c;
2534 tmpstr[i++] = 0;
2535 *vp = 0;
2536 if (setjmp(bus_error_jmp) == 0) {
2537 catch_memory_errors = 1;
2538 sync();
2539 *vp = kallsyms_lookup_name(tmpstr);
2540 sync();
2542 catch_memory_errors = 0;
2543 if (!(*vp)) {
2544 printf("unknown symbol '%s'\n", tmpstr);
2545 return 0;
2547 return 1;
2550 d = hexdigit(c);
2551 if (d == EOF) {
2552 termch = c;
2553 return 0;
2555 v = 0;
2556 do {
2557 v = (v << 4) + d;
2558 c = inchar();
2559 d = hexdigit(c);
2560 } while (d != EOF);
2561 termch = c;
2562 *vp = v;
2563 return 1;
2566 static void
2567 scannl(void)
2569 int c;
2571 c = termch;
2572 termch = 0;
2573 while( c != '\n' )
2574 c = inchar();
2577 static int hexdigit(int c)
2579 if( '0' <= c && c <= '9' )
2580 return c - '0';
2581 if( 'A' <= c && c <= 'F' )
2582 return c - ('A' - 10);
2583 if( 'a' <= c && c <= 'f' )
2584 return c - ('a' - 10);
2585 return EOF;
2588 void
2589 getstring(char *s, int size)
2591 int c;
2593 c = skipbl();
2594 do {
2595 if( size > 1 ){
2596 *s++ = c;
2597 --size;
2599 c = inchar();
2600 } while( c != ' ' && c != '\t' && c != '\n' );
2601 termch = c;
2602 *s = 0;
2605 static char line[256];
2606 static char *lineptr;
2608 static void
2609 flush_input(void)
2611 lineptr = NULL;
2614 static int
2615 inchar(void)
2617 if (lineptr == NULL || *lineptr == 0) {
2618 if (xmon_gets(line, sizeof(line)) == NULL) {
2619 lineptr = NULL;
2620 return EOF;
2622 lineptr = line;
2624 return *lineptr++;
2627 static void
2628 take_input(char *str)
2630 lineptr = str;
2634 static void
2635 symbol_lookup(void)
2637 int type = inchar();
2638 unsigned long addr;
2639 static char tmp[64];
2641 switch (type) {
2642 case 'a':
2643 if (scanhex(&addr))
2644 xmon_print_symbol(addr, ": ", "\n");
2645 termch = 0;
2646 break;
2647 case 's':
2648 getstring(tmp, 64);
2649 if (setjmp(bus_error_jmp) == 0) {
2650 catch_memory_errors = 1;
2651 sync();
2652 addr = kallsyms_lookup_name(tmp);
2653 if (addr)
2654 printf("%s: %lx\n", tmp, addr);
2655 else
2656 printf("Symbol '%s' not found.\n", tmp);
2657 sync();
2659 catch_memory_errors = 0;
2660 termch = 0;
2661 break;
2666 /* Print an address in numeric and symbolic form (if possible) */
2667 static void xmon_print_symbol(unsigned long address, const char *mid,
2668 const char *after)
2670 char *modname;
2671 const char *name = NULL;
2672 unsigned long offset, size;
2674 printf(REG, address);
2675 if (setjmp(bus_error_jmp) == 0) {
2676 catch_memory_errors = 1;
2677 sync();
2678 name = kallsyms_lookup(address, &size, &offset, &modname,
2679 tmpstr);
2680 sync();
2681 /* wait a little while to see if we get a machine check */
2682 __delay(200);
2685 catch_memory_errors = 0;
2687 if (name) {
2688 printf("%s%s+%#lx/%#lx", mid, name, offset, size);
2689 if (modname)
2690 printf(" [%s]", modname);
2692 printf("%s", after);
2695 #ifdef CONFIG_PPC_BOOK3S_64
2696 void dump_segments(void)
2698 int i;
2699 unsigned long esid,vsid,valid;
2700 unsigned long llp;
2702 printf("SLB contents of cpu 0x%x\n", smp_processor_id());
2704 for (i = 0; i < mmu_slb_size; i++) {
2705 asm volatile("slbmfee %0,%1" : "=r" (esid) : "r" (i));
2706 asm volatile("slbmfev %0,%1" : "=r" (vsid) : "r" (i));
2707 valid = (esid & SLB_ESID_V);
2708 if (valid | esid | vsid) {
2709 printf("%02d %016lx %016lx", i, esid, vsid);
2710 if (valid) {
2711 llp = vsid & SLB_VSID_LLP;
2712 if (vsid & SLB_VSID_B_1T) {
2713 printf(" 1T ESID=%9lx VSID=%13lx LLP:%3lx \n",
2714 GET_ESID_1T(esid),
2715 (vsid & ~SLB_VSID_B) >> SLB_VSID_SHIFT_1T,
2716 llp);
2717 } else {
2718 printf(" 256M ESID=%9lx VSID=%13lx LLP:%3lx \n",
2719 GET_ESID(esid),
2720 (vsid & ~SLB_VSID_B) >> SLB_VSID_SHIFT,
2721 llp);
2723 } else
2724 printf("\n");
2728 #endif
2730 #ifdef CONFIG_PPC_STD_MMU_32
2731 void dump_segments(void)
2733 int i;
2735 printf("sr0-15 =");
2736 for (i = 0; i < 16; ++i)
2737 printf(" %x", mfsrin(i));
2738 printf("\n");
2740 #endif
2742 #ifdef CONFIG_44x
2743 static void dump_tlb_44x(void)
2745 int i;
2747 for (i = 0; i < PPC44x_TLB_SIZE; i++) {
2748 unsigned long w0,w1,w2;
2749 asm volatile("tlbre %0,%1,0" : "=r" (w0) : "r" (i));
2750 asm volatile("tlbre %0,%1,1" : "=r" (w1) : "r" (i));
2751 asm volatile("tlbre %0,%1,2" : "=r" (w2) : "r" (i));
2752 printf("[%02x] %08x %08x %08x ", i, w0, w1, w2);
2753 if (w0 & PPC44x_TLB_VALID) {
2754 printf("V %08x -> %01x%08x %c%c%c%c%c",
2755 w0 & PPC44x_TLB_EPN_MASK,
2756 w1 & PPC44x_TLB_ERPN_MASK,
2757 w1 & PPC44x_TLB_RPN_MASK,
2758 (w2 & PPC44x_TLB_W) ? 'W' : 'w',
2759 (w2 & PPC44x_TLB_I) ? 'I' : 'i',
2760 (w2 & PPC44x_TLB_M) ? 'M' : 'm',
2761 (w2 & PPC44x_TLB_G) ? 'G' : 'g',
2762 (w2 & PPC44x_TLB_E) ? 'E' : 'e');
2764 printf("\n");
2767 #endif /* CONFIG_44x */
2769 #ifdef CONFIG_PPC_BOOK3E
2770 static void dump_tlb_book3e(void)
2772 u32 mmucfg, pidmask, lpidmask;
2773 u64 ramask;
2774 int i, tlb, ntlbs, pidsz, lpidsz, rasz, lrat = 0;
2775 int mmu_version;
2776 static const char *pgsz_names[] = {
2777 " 1K",
2778 " 2K",
2779 " 4K",
2780 " 8K",
2781 " 16K",
2782 " 32K",
2783 " 64K",
2784 "128K",
2785 "256K",
2786 "512K",
2787 " 1M",
2788 " 2M",
2789 " 4M",
2790 " 8M",
2791 " 16M",
2792 " 32M",
2793 " 64M",
2794 "128M",
2795 "256M",
2796 "512M",
2797 " 1G",
2798 " 2G",
2799 " 4G",
2800 " 8G",
2801 " 16G",
2802 " 32G",
2803 " 64G",
2804 "128G",
2805 "256G",
2806 "512G",
2807 " 1T",
2808 " 2T",
2811 /* Gather some infos about the MMU */
2812 mmucfg = mfspr(SPRN_MMUCFG);
2813 mmu_version = (mmucfg & 3) + 1;
2814 ntlbs = ((mmucfg >> 2) & 3) + 1;
2815 pidsz = ((mmucfg >> 6) & 0x1f) + 1;
2816 lpidsz = (mmucfg >> 24) & 0xf;
2817 rasz = (mmucfg >> 16) & 0x7f;
2818 if ((mmu_version > 1) && (mmucfg & 0x10000))
2819 lrat = 1;
2820 printf("Book3E MMU MAV=%d.0,%d TLBs,%d-bit PID,%d-bit LPID,%d-bit RA\n",
2821 mmu_version, ntlbs, pidsz, lpidsz, rasz);
2822 pidmask = (1ul << pidsz) - 1;
2823 lpidmask = (1ul << lpidsz) - 1;
2824 ramask = (1ull << rasz) - 1;
2826 for (tlb = 0; tlb < ntlbs; tlb++) {
2827 u32 tlbcfg;
2828 int nent, assoc, new_cc = 1;
2829 printf("TLB %d:\n------\n", tlb);
2830 switch(tlb) {
2831 case 0:
2832 tlbcfg = mfspr(SPRN_TLB0CFG);
2833 break;
2834 case 1:
2835 tlbcfg = mfspr(SPRN_TLB1CFG);
2836 break;
2837 case 2:
2838 tlbcfg = mfspr(SPRN_TLB2CFG);
2839 break;
2840 case 3:
2841 tlbcfg = mfspr(SPRN_TLB3CFG);
2842 break;
2843 default:
2844 printf("Unsupported TLB number !\n");
2845 continue;
2847 nent = tlbcfg & 0xfff;
2848 assoc = (tlbcfg >> 24) & 0xff;
2849 for (i = 0; i < nent; i++) {
2850 u32 mas0 = MAS0_TLBSEL(tlb);
2851 u32 mas1 = MAS1_TSIZE(BOOK3E_PAGESZ_4K);
2852 u64 mas2 = 0;
2853 u64 mas7_mas3;
2854 int esel = i, cc = i;
2856 if (assoc != 0) {
2857 cc = i / assoc;
2858 esel = i % assoc;
2859 mas2 = cc * 0x1000;
2862 mas0 |= MAS0_ESEL(esel);
2863 mtspr(SPRN_MAS0, mas0);
2864 mtspr(SPRN_MAS1, mas1);
2865 mtspr(SPRN_MAS2, mas2);
2866 asm volatile("tlbre 0,0,0" : : : "memory");
2867 mas1 = mfspr(SPRN_MAS1);
2868 mas2 = mfspr(SPRN_MAS2);
2869 mas7_mas3 = mfspr(SPRN_MAS7_MAS3);
2870 if (assoc && (i % assoc) == 0)
2871 new_cc = 1;
2872 if (!(mas1 & MAS1_VALID))
2873 continue;
2874 if (assoc == 0)
2875 printf("%04x- ", i);
2876 else if (new_cc)
2877 printf("%04x-%c", cc, 'A' + esel);
2878 else
2879 printf(" |%c", 'A' + esel);
2880 new_cc = 0;
2881 printf(" %016llx %04x %s %c%c AS%c",
2882 mas2 & ~0x3ffull,
2883 (mas1 >> 16) & 0x3fff,
2884 pgsz_names[(mas1 >> 7) & 0x1f],
2885 mas1 & MAS1_IND ? 'I' : ' ',
2886 mas1 & MAS1_IPROT ? 'P' : ' ',
2887 mas1 & MAS1_TS ? '1' : '0');
2888 printf(" %c%c%c%c%c%c%c",
2889 mas2 & MAS2_X0 ? 'a' : ' ',
2890 mas2 & MAS2_X1 ? 'v' : ' ',
2891 mas2 & MAS2_W ? 'w' : ' ',
2892 mas2 & MAS2_I ? 'i' : ' ',
2893 mas2 & MAS2_M ? 'm' : ' ',
2894 mas2 & MAS2_G ? 'g' : ' ',
2895 mas2 & MAS2_E ? 'e' : ' ');
2896 printf(" %016llx", mas7_mas3 & ramask & ~0x7ffull);
2897 if (mas1 & MAS1_IND)
2898 printf(" %s\n",
2899 pgsz_names[(mas7_mas3 >> 1) & 0x1f]);
2900 else
2901 printf(" U%c%c%c S%c%c%c\n",
2902 mas7_mas3 & MAS3_UX ? 'x' : ' ',
2903 mas7_mas3 & MAS3_UW ? 'w' : ' ',
2904 mas7_mas3 & MAS3_UR ? 'r' : ' ',
2905 mas7_mas3 & MAS3_SX ? 'x' : ' ',
2906 mas7_mas3 & MAS3_SW ? 'w' : ' ',
2907 mas7_mas3 & MAS3_SR ? 'r' : ' ');
2911 #endif /* CONFIG_PPC_BOOK3E */
2913 static void xmon_init(int enable)
2915 if (enable) {
2916 __debugger = xmon;
2917 __debugger_ipi = xmon_ipi;
2918 __debugger_bpt = xmon_bpt;
2919 __debugger_sstep = xmon_sstep;
2920 __debugger_iabr_match = xmon_iabr_match;
2921 __debugger_break_match = xmon_break_match;
2922 __debugger_fault_handler = xmon_fault_handler;
2923 } else {
2924 __debugger = NULL;
2925 __debugger_ipi = NULL;
2926 __debugger_bpt = NULL;
2927 __debugger_sstep = NULL;
2928 __debugger_iabr_match = NULL;
2929 __debugger_break_match = NULL;
2930 __debugger_fault_handler = NULL;
2934 #ifdef CONFIG_MAGIC_SYSRQ
2935 static void sysrq_handle_xmon(int key)
2937 /* ensure xmon is enabled */
2938 xmon_init(1);
2939 debugger(get_irq_regs());
2942 static struct sysrq_key_op sysrq_xmon_op = {
2943 .handler = sysrq_handle_xmon,
2944 .help_msg = "xmon(x)",
2945 .action_msg = "Entering xmon",
2948 static int __init setup_xmon_sysrq(void)
2950 register_sysrq_key('x', &sysrq_xmon_op);
2951 return 0;
2953 __initcall(setup_xmon_sysrq);
2954 #endif /* CONFIG_MAGIC_SYSRQ */
2956 static int __initdata xmon_early, xmon_off;
2958 static int __init early_parse_xmon(char *p)
2960 if (!p || strncmp(p, "early", 5) == 0) {
2961 /* just "xmon" is equivalent to "xmon=early" */
2962 xmon_init(1);
2963 xmon_early = 1;
2964 } else if (strncmp(p, "on", 2) == 0)
2965 xmon_init(1);
2966 else if (strncmp(p, "off", 3) == 0)
2967 xmon_off = 1;
2968 else if (strncmp(p, "nobt", 4) == 0)
2969 xmon_no_auto_backtrace = 1;
2970 else
2971 return 1;
2973 return 0;
2975 early_param("xmon", early_parse_xmon);
2977 void __init xmon_setup(void)
2979 #ifdef CONFIG_XMON_DEFAULT
2980 if (!xmon_off)
2981 xmon_init(1);
2982 #endif
2983 if (xmon_early)
2984 debugger(NULL);
2987 #ifdef CONFIG_SPU_BASE
2989 struct spu_info {
2990 struct spu *spu;
2991 u64 saved_mfc_sr1_RW;
2992 u32 saved_spu_runcntl_RW;
2993 unsigned long dump_addr;
2994 u8 stopped_ok;
2997 #define XMON_NUM_SPUS 16 /* Enough for current hardware */
2999 static struct spu_info spu_info[XMON_NUM_SPUS];
3001 void xmon_register_spus(struct list_head *list)
3003 struct spu *spu;
3005 list_for_each_entry(spu, list, full_list) {
3006 if (spu->number >= XMON_NUM_SPUS) {
3007 WARN_ON(1);
3008 continue;
3011 spu_info[spu->number].spu = spu;
3012 spu_info[spu->number].stopped_ok = 0;
3013 spu_info[spu->number].dump_addr = (unsigned long)
3014 spu_info[spu->number].spu->local_store;
3018 static void stop_spus(void)
3020 struct spu *spu;
3021 int i;
3022 u64 tmp;
3024 for (i = 0; i < XMON_NUM_SPUS; i++) {
3025 if (!spu_info[i].spu)
3026 continue;
3028 if (setjmp(bus_error_jmp) == 0) {
3029 catch_memory_errors = 1;
3030 sync();
3032 spu = spu_info[i].spu;
3034 spu_info[i].saved_spu_runcntl_RW =
3035 in_be32(&spu->problem->spu_runcntl_RW);
3037 tmp = spu_mfc_sr1_get(spu);
3038 spu_info[i].saved_mfc_sr1_RW = tmp;
3040 tmp &= ~MFC_STATE1_MASTER_RUN_CONTROL_MASK;
3041 spu_mfc_sr1_set(spu, tmp);
3043 sync();
3044 __delay(200);
3046 spu_info[i].stopped_ok = 1;
3048 printf("Stopped spu %.2d (was %s)\n", i,
3049 spu_info[i].saved_spu_runcntl_RW ?
3050 "running" : "stopped");
3051 } else {
3052 catch_memory_errors = 0;
3053 printf("*** Error stopping spu %.2d\n", i);
3055 catch_memory_errors = 0;
3059 static void restart_spus(void)
3061 struct spu *spu;
3062 int i;
3064 for (i = 0; i < XMON_NUM_SPUS; i++) {
3065 if (!spu_info[i].spu)
3066 continue;
3068 if (!spu_info[i].stopped_ok) {
3069 printf("*** Error, spu %d was not successfully stopped"
3070 ", not restarting\n", i);
3071 continue;
3074 if (setjmp(bus_error_jmp) == 0) {
3075 catch_memory_errors = 1;
3076 sync();
3078 spu = spu_info[i].spu;
3079 spu_mfc_sr1_set(spu, spu_info[i].saved_mfc_sr1_RW);
3080 out_be32(&spu->problem->spu_runcntl_RW,
3081 spu_info[i].saved_spu_runcntl_RW);
3083 sync();
3084 __delay(200);
3086 printf("Restarted spu %.2d\n", i);
3087 } else {
3088 catch_memory_errors = 0;
3089 printf("*** Error restarting spu %.2d\n", i);
3091 catch_memory_errors = 0;
3095 #define DUMP_WIDTH 23
3096 #define DUMP_VALUE(format, field, value) \
3097 do { \
3098 if (setjmp(bus_error_jmp) == 0) { \
3099 catch_memory_errors = 1; \
3100 sync(); \
3101 printf(" %-*s = "format"\n", DUMP_WIDTH, \
3102 #field, value); \
3103 sync(); \
3104 __delay(200); \
3105 } else { \
3106 catch_memory_errors = 0; \
3107 printf(" %-*s = *** Error reading field.\n", \
3108 DUMP_WIDTH, #field); \
3110 catch_memory_errors = 0; \
3111 } while (0)
3113 #define DUMP_FIELD(obj, format, field) \
3114 DUMP_VALUE(format, field, obj->field)
3116 static void dump_spu_fields(struct spu *spu)
3118 printf("Dumping spu fields at address %p:\n", spu);
3120 DUMP_FIELD(spu, "0x%x", number);
3121 DUMP_FIELD(spu, "%s", name);
3122 DUMP_FIELD(spu, "0x%lx", local_store_phys);
3123 DUMP_FIELD(spu, "0x%p", local_store);
3124 DUMP_FIELD(spu, "0x%lx", ls_size);
3125 DUMP_FIELD(spu, "0x%x", node);
3126 DUMP_FIELD(spu, "0x%lx", flags);
3127 DUMP_FIELD(spu, "%d", class_0_pending);
3128 DUMP_FIELD(spu, "0x%lx", class_0_dar);
3129 DUMP_FIELD(spu, "0x%lx", class_1_dar);
3130 DUMP_FIELD(spu, "0x%lx", class_1_dsisr);
3131 DUMP_FIELD(spu, "0x%lx", irqs[0]);
3132 DUMP_FIELD(spu, "0x%lx", irqs[1]);
3133 DUMP_FIELD(spu, "0x%lx", irqs[2]);
3134 DUMP_FIELD(spu, "0x%x", slb_replace);
3135 DUMP_FIELD(spu, "%d", pid);
3136 DUMP_FIELD(spu, "0x%p", mm);
3137 DUMP_FIELD(spu, "0x%p", ctx);
3138 DUMP_FIELD(spu, "0x%p", rq);
3139 DUMP_FIELD(spu, "0x%p", timestamp);
3140 DUMP_FIELD(spu, "0x%lx", problem_phys);
3141 DUMP_FIELD(spu, "0x%p", problem);
3142 DUMP_VALUE("0x%x", problem->spu_runcntl_RW,
3143 in_be32(&spu->problem->spu_runcntl_RW));
3144 DUMP_VALUE("0x%x", problem->spu_status_R,
3145 in_be32(&spu->problem->spu_status_R));
3146 DUMP_VALUE("0x%x", problem->spu_npc_RW,
3147 in_be32(&spu->problem->spu_npc_RW));
3148 DUMP_FIELD(spu, "0x%p", priv2);
3149 DUMP_FIELD(spu, "0x%p", pdata);
3153 spu_inst_dump(unsigned long adr, long count, int praddr)
3155 return generic_inst_dump(adr, count, praddr, print_insn_spu);
3158 static void dump_spu_ls(unsigned long num, int subcmd)
3160 unsigned long offset, addr, ls_addr;
3162 if (setjmp(bus_error_jmp) == 0) {
3163 catch_memory_errors = 1;
3164 sync();
3165 ls_addr = (unsigned long)spu_info[num].spu->local_store;
3166 sync();
3167 __delay(200);
3168 } else {
3169 catch_memory_errors = 0;
3170 printf("*** Error: accessing spu info for spu %d\n", num);
3171 return;
3173 catch_memory_errors = 0;
3175 if (scanhex(&offset))
3176 addr = ls_addr + offset;
3177 else
3178 addr = spu_info[num].dump_addr;
3180 if (addr >= ls_addr + LS_SIZE) {
3181 printf("*** Error: address outside of local store\n");
3182 return;
3185 switch (subcmd) {
3186 case 'i':
3187 addr += spu_inst_dump(addr, 16, 1);
3188 last_cmd = "sdi\n";
3189 break;
3190 default:
3191 prdump(addr, 64);
3192 addr += 64;
3193 last_cmd = "sd\n";
3194 break;
3197 spu_info[num].dump_addr = addr;
3200 static int do_spu_cmd(void)
3202 static unsigned long num = 0;
3203 int cmd, subcmd = 0;
3205 cmd = inchar();
3206 switch (cmd) {
3207 case 's':
3208 stop_spus();
3209 break;
3210 case 'r':
3211 restart_spus();
3212 break;
3213 case 'd':
3214 subcmd = inchar();
3215 if (isxdigit(subcmd) || subcmd == '\n')
3216 termch = subcmd;
3217 case 'f':
3218 scanhex(&num);
3219 if (num >= XMON_NUM_SPUS || !spu_info[num].spu) {
3220 printf("*** Error: invalid spu number\n");
3221 return 0;
3224 switch (cmd) {
3225 case 'f':
3226 dump_spu_fields(spu_info[num].spu);
3227 break;
3228 default:
3229 dump_spu_ls(num, subcmd);
3230 break;
3233 break;
3234 default:
3235 return -1;
3238 return 0;
3240 #else /* ! CONFIG_SPU_BASE */
3241 static int do_spu_cmd(void)
3243 return -1;
3245 #endif