Linux 3.16-rc2
[linux/fpc-iii.git] / arch / powerpc / xmon / xmon.c
blobd199bfa2f1fa5ff6610c0413ff0795d6ca42c6a7
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>
28 #include <asm/ptrace.h>
29 #include <asm/string.h>
30 #include <asm/prom.h>
31 #include <asm/machdep.h>
32 #include <asm/xmon.h>
33 #include <asm/processor.h>
34 #include <asm/pgtable.h>
35 #include <asm/mmu.h>
36 #include <asm/mmu_context.h>
37 #include <asm/cputable.h>
38 #include <asm/rtas.h>
39 #include <asm/sstep.h>
40 #include <asm/irq_regs.h>
41 #include <asm/spu.h>
42 #include <asm/spu_priv1.h>
43 #include <asm/setjmp.h>
44 #include <asm/reg.h>
45 #include <asm/debug.h>
46 #include <asm/hw_breakpoint.h>
48 #ifdef CONFIG_PPC64
49 #include <asm/hvcall.h>
50 #include <asm/paca.h>
51 #endif
53 #include "nonstdio.h"
54 #include "dis-asm.h"
56 #ifdef CONFIG_SMP
57 static cpumask_t cpus_in_xmon = CPU_MASK_NONE;
58 static unsigned long xmon_taken = 1;
59 static int xmon_owner;
60 static int xmon_gate;
61 #else
62 #define xmon_owner 0
63 #endif /* CONFIG_SMP */
65 static unsigned long in_xmon __read_mostly = 0;
67 static unsigned long adrs;
68 static int size = 1;
69 #define MAX_DUMP (128 * 1024)
70 static unsigned long ndump = 64;
71 static unsigned long nidump = 16;
72 static unsigned long ncsum = 4096;
73 static int termch;
74 static char tmpstr[128];
76 static long bus_error_jmp[JMP_BUF_LEN];
77 static int catch_memory_errors;
78 static long *xmon_fault_jmp[NR_CPUS];
80 /* Breakpoint stuff */
81 struct bpt {
82 unsigned long address;
83 unsigned int instr[2];
84 atomic_t ref_count;
85 int enabled;
86 unsigned long pad;
89 /* Bits in bpt.enabled */
90 #define BP_IABR_TE 1 /* IABR translation enabled */
91 #define BP_IABR 2
92 #define BP_TRAP 8
93 #define BP_DABR 0x10
95 #define NBPTS 256
96 static struct bpt bpts[NBPTS];
97 static struct bpt dabr;
98 static struct bpt *iabr;
99 static unsigned bpinstr = 0x7fe00008; /* trap */
101 #define BP_NUM(bp) ((bp) - bpts + 1)
103 /* Prototypes */
104 static int cmds(struct pt_regs *);
105 static int mread(unsigned long, void *, int);
106 static int mwrite(unsigned long, void *, int);
107 static int handle_fault(struct pt_regs *);
108 static void byterev(unsigned char *, int);
109 static void memex(void);
110 static int bsesc(void);
111 static void dump(void);
112 static void prdump(unsigned long, long);
113 static int ppc_inst_dump(unsigned long, long, int);
114 static void dump_log_buf(void);
115 static void backtrace(struct pt_regs *);
116 static void excprint(struct pt_regs *);
117 static void prregs(struct pt_regs *);
118 static void memops(int);
119 static void memlocate(void);
120 static void memzcan(void);
121 static void memdiffs(unsigned char *, unsigned char *, unsigned, unsigned);
122 int skipbl(void);
123 int scanhex(unsigned long *valp);
124 static void scannl(void);
125 static int hexdigit(int);
126 void getstring(char *, int);
127 static void flush_input(void);
128 static int inchar(void);
129 static void take_input(char *);
130 static unsigned long read_spr(int);
131 static void write_spr(int, unsigned long);
132 static void super_regs(void);
133 static void remove_bpts(void);
134 static void insert_bpts(void);
135 static void remove_cpu_bpts(void);
136 static void insert_cpu_bpts(void);
137 static struct bpt *at_breakpoint(unsigned long pc);
138 static struct bpt *in_breakpoint_table(unsigned long pc, unsigned long *offp);
139 static int do_step(struct pt_regs *);
140 static void bpt_cmds(void);
141 static void cacheflush(void);
142 static int cpu_cmd(void);
143 static void csum(void);
144 static void bootcmds(void);
145 static void proccall(void);
146 void dump_segments(void);
147 static void symbol_lookup(void);
148 static void xmon_show_stack(unsigned long sp, unsigned long lr,
149 unsigned long pc);
150 static void xmon_print_symbol(unsigned long address, const char *mid,
151 const char *after);
152 static const char *getvecname(unsigned long vec);
154 static int do_spu_cmd(void);
156 #ifdef CONFIG_44x
157 static void dump_tlb_44x(void);
158 #endif
159 #ifdef CONFIG_PPC_BOOK3E
160 static void dump_tlb_book3e(void);
161 #endif
163 static int xmon_no_auto_backtrace;
165 extern void xmon_enter(void);
166 extern void xmon_leave(void);
168 #ifdef CONFIG_PPC64
169 #define REG "%.16lx"
170 #else
171 #define REG "%.8lx"
172 #endif
174 #ifdef __LITTLE_ENDIAN__
175 #define GETWORD(v) (((v)[3] << 24) + ((v)[2] << 16) + ((v)[1] << 8) + (v)[0])
176 #else
177 #define GETWORD(v) (((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
178 #endif
180 #define isxdigit(c) (('0' <= (c) && (c) <= '9') \
181 || ('a' <= (c) && (c) <= 'f') \
182 || ('A' <= (c) && (c) <= 'F'))
183 #define isalnum(c) (('0' <= (c) && (c) <= '9') \
184 || ('a' <= (c) && (c) <= 'z') \
185 || ('A' <= (c) && (c) <= 'Z'))
186 #define isspace(c) (c == ' ' || c == '\t' || c == 10 || c == 13 || c == 0)
188 static char *help_string = "\
189 Commands:\n\
190 b show breakpoints\n\
191 bd set data breakpoint\n\
192 bi set instruction breakpoint\n\
193 bc clear breakpoint\n"
194 #ifdef CONFIG_SMP
196 c print cpus stopped in xmon\n\
197 c# try to switch to cpu number h (in hex)\n"
198 #endif
200 C checksum\n\
201 d dump bytes\n\
202 di dump instructions\n\
203 df dump float values\n\
204 dd dump double values\n\
205 dl dump the kernel log buffer\n"
206 #ifdef CONFIG_PPC64
208 dp[#] dump paca for current cpu, or cpu #\n\
209 dpa dump paca for all possible cpus\n"
210 #endif
212 dr dump stream of raw bytes\n\
213 e print exception information\n\
214 f flush cache\n\
215 la lookup symbol+offset of specified address\n\
216 ls lookup address of specified symbol\n\
217 m examine/change memory\n\
218 mm move a block of memory\n\
219 ms set a block of memory\n\
220 md compare two blocks of memory\n\
221 ml locate a block of memory\n\
222 mz zero a block of memory\n\
223 mi show information about memory allocation\n\
224 p call a procedure\n\
225 r print registers\n\
226 s single step\n"
227 #ifdef CONFIG_SPU_BASE
228 " ss stop execution on all spus\n\
229 sr restore execution on stopped spus\n\
230 sf # dump spu fields for spu # (in hex)\n\
231 sd # dump spu local store for spu # (in hex)\n\
232 sdi # disassemble spu local store for spu # (in hex)\n"
233 #endif
234 " S print special registers\n\
235 t print backtrace\n\
236 x exit monitor and recover\n\
237 X exit monitor and dont recover\n"
238 #if defined(CONFIG_PPC64) && !defined(CONFIG_PPC_BOOK3E)
239 " u dump segment table or SLB\n"
240 #elif defined(CONFIG_PPC_STD_MMU_32)
241 " u dump segment registers\n"
242 #elif defined(CONFIG_44x) || defined(CONFIG_PPC_BOOK3E)
243 " u dump TLB\n"
244 #endif
245 " ? help\n"
246 " zr reboot\n\
247 zh halt\n"
250 static struct pt_regs *xmon_regs;
252 static inline void sync(void)
254 asm volatile("sync; isync");
257 static inline void store_inst(void *p)
259 asm volatile ("dcbst 0,%0; sync; icbi 0,%0; isync" : : "r" (p));
262 static inline void cflush(void *p)
264 asm volatile ("dcbf 0,%0; icbi 0,%0" : : "r" (p));
267 static inline void cinval(void *p)
269 asm volatile ("dcbi 0,%0; icbi 0,%0" : : "r" (p));
273 * Disable surveillance (the service processor watchdog function)
274 * while we are in xmon.
275 * XXX we should re-enable it when we leave. :)
277 #define SURVEILLANCE_TOKEN 9000
279 static inline void disable_surveillance(void)
281 #ifdef CONFIG_PPC_PSERIES
282 /* Since this can't be a module, args should end up below 4GB. */
283 static struct rtas_args args;
286 * At this point we have got all the cpus we can into
287 * xmon, so there is hopefully no other cpu calling RTAS
288 * at the moment, even though we don't take rtas.lock.
289 * If we did try to take rtas.lock there would be a
290 * real possibility of deadlock.
292 args.token = rtas_token("set-indicator");
293 if (args.token == RTAS_UNKNOWN_SERVICE)
294 return;
295 args.nargs = 3;
296 args.nret = 1;
297 args.rets = &args.args[3];
298 args.args[0] = SURVEILLANCE_TOKEN;
299 args.args[1] = 0;
300 args.args[2] = 0;
301 enter_rtas(__pa(&args));
302 #endif /* CONFIG_PPC_PSERIES */
305 #ifdef CONFIG_SMP
306 static int xmon_speaker;
308 static void get_output_lock(void)
310 int me = smp_processor_id() + 0x100;
311 int last_speaker = 0, prev;
312 long timeout;
314 if (xmon_speaker == me)
315 return;
317 for (;;) {
318 last_speaker = cmpxchg(&xmon_speaker, 0, me);
319 if (last_speaker == 0)
320 return;
323 * Wait a full second for the lock, we might be on a slow
324 * console, but check every 100us.
326 timeout = 10000;
327 while (xmon_speaker == last_speaker) {
328 if (--timeout > 0) {
329 udelay(100);
330 continue;
333 /* hostile takeover */
334 prev = cmpxchg(&xmon_speaker, last_speaker, me);
335 if (prev == last_speaker)
336 return;
337 break;
342 static void release_output_lock(void)
344 xmon_speaker = 0;
347 int cpus_are_in_xmon(void)
349 return !cpumask_empty(&cpus_in_xmon);
351 #endif
353 static inline int unrecoverable_excp(struct pt_regs *regs)
355 #if defined(CONFIG_4xx) || defined(CONFIG_PPC_BOOK3E)
356 /* We have no MSR_RI bit on 4xx or Book3e, so we simply return false */
357 return 0;
358 #else
359 return ((regs->msr & MSR_RI) == 0);
360 #endif
363 static int xmon_core(struct pt_regs *regs, int fromipi)
365 int cmd = 0;
366 struct bpt *bp;
367 long recurse_jmp[JMP_BUF_LEN];
368 unsigned long offset;
369 unsigned long flags;
370 #ifdef CONFIG_SMP
371 int cpu;
372 int secondary;
373 unsigned long timeout;
374 #endif
376 local_irq_save(flags);
378 bp = in_breakpoint_table(regs->nip, &offset);
379 if (bp != NULL) {
380 regs->nip = bp->address + offset;
381 atomic_dec(&bp->ref_count);
384 remove_cpu_bpts();
386 #ifdef CONFIG_SMP
387 cpu = smp_processor_id();
388 if (cpumask_test_cpu(cpu, &cpus_in_xmon)) {
389 get_output_lock();
390 excprint(regs);
391 printf("cpu 0x%x: Exception %lx %s in xmon, "
392 "returning to main loop\n",
393 cpu, regs->trap, getvecname(TRAP(regs)));
394 release_output_lock();
395 longjmp(xmon_fault_jmp[cpu], 1);
398 if (setjmp(recurse_jmp) != 0) {
399 if (!in_xmon || !xmon_gate) {
400 get_output_lock();
401 printf("xmon: WARNING: bad recursive fault "
402 "on cpu 0x%x\n", cpu);
403 release_output_lock();
404 goto waiting;
406 secondary = !(xmon_taken && cpu == xmon_owner);
407 goto cmdloop;
410 xmon_fault_jmp[cpu] = recurse_jmp;
412 bp = NULL;
413 if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) == (MSR_IR|MSR_64BIT))
414 bp = at_breakpoint(regs->nip);
415 if (bp || unrecoverable_excp(regs))
416 fromipi = 0;
418 if (!fromipi) {
419 get_output_lock();
420 excprint(regs);
421 if (bp) {
422 printf("cpu 0x%x stopped at breakpoint 0x%lx (",
423 cpu, BP_NUM(bp));
424 xmon_print_symbol(regs->nip, " ", ")\n");
426 if (unrecoverable_excp(regs))
427 printf("WARNING: exception is not recoverable, "
428 "can't continue\n");
429 release_output_lock();
432 cpumask_set_cpu(cpu, &cpus_in_xmon);
434 waiting:
435 secondary = 1;
436 while (secondary && !xmon_gate) {
437 if (in_xmon == 0) {
438 if (fromipi)
439 goto leave;
440 secondary = test_and_set_bit(0, &in_xmon);
442 barrier();
445 if (!secondary && !xmon_gate) {
446 /* we are the first cpu to come in */
447 /* interrupt other cpu(s) */
448 int ncpus = num_online_cpus();
450 xmon_owner = cpu;
451 mb();
452 if (ncpus > 1) {
453 smp_send_debugger_break();
454 /* wait for other cpus to come in */
455 for (timeout = 100000000; timeout != 0; --timeout) {
456 if (cpumask_weight(&cpus_in_xmon) >= ncpus)
457 break;
458 barrier();
461 remove_bpts();
462 disable_surveillance();
463 /* for breakpoint or single step, print the current instr. */
464 if (bp || TRAP(regs) == 0xd00)
465 ppc_inst_dump(regs->nip, 1, 0);
466 printf("enter ? for help\n");
467 mb();
468 xmon_gate = 1;
469 barrier();
472 cmdloop:
473 while (in_xmon) {
474 if (secondary) {
475 if (cpu == xmon_owner) {
476 if (!test_and_set_bit(0, &xmon_taken)) {
477 secondary = 0;
478 continue;
480 /* missed it */
481 while (cpu == xmon_owner)
482 barrier();
484 barrier();
485 } else {
486 cmd = cmds(regs);
487 if (cmd != 0) {
488 /* exiting xmon */
489 insert_bpts();
490 xmon_gate = 0;
491 wmb();
492 in_xmon = 0;
493 break;
495 /* have switched to some other cpu */
496 secondary = 1;
499 leave:
500 cpumask_clear_cpu(cpu, &cpus_in_xmon);
501 xmon_fault_jmp[cpu] = NULL;
502 #else
503 /* UP is simple... */
504 if (in_xmon) {
505 printf("Exception %lx %s in xmon, returning to main loop\n",
506 regs->trap, getvecname(TRAP(regs)));
507 longjmp(xmon_fault_jmp[0], 1);
509 if (setjmp(recurse_jmp) == 0) {
510 xmon_fault_jmp[0] = recurse_jmp;
511 in_xmon = 1;
513 excprint(regs);
514 bp = at_breakpoint(regs->nip);
515 if (bp) {
516 printf("Stopped at breakpoint %lx (", BP_NUM(bp));
517 xmon_print_symbol(regs->nip, " ", ")\n");
519 if (unrecoverable_excp(regs))
520 printf("WARNING: exception is not recoverable, "
521 "can't continue\n");
522 remove_bpts();
523 disable_surveillance();
524 /* for breakpoint or single step, print the current instr. */
525 if (bp || TRAP(regs) == 0xd00)
526 ppc_inst_dump(regs->nip, 1, 0);
527 printf("enter ? for help\n");
530 cmd = cmds(regs);
532 insert_bpts();
533 in_xmon = 0;
534 #endif
536 #ifdef CONFIG_BOOKE
537 if (regs->msr & MSR_DE) {
538 bp = at_breakpoint(regs->nip);
539 if (bp != NULL) {
540 regs->nip = (unsigned long) &bp->instr[0];
541 atomic_inc(&bp->ref_count);
544 #else
545 if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) == (MSR_IR|MSR_64BIT)) {
546 bp = at_breakpoint(regs->nip);
547 if (bp != NULL) {
548 int stepped = emulate_step(regs, bp->instr[0]);
549 if (stepped == 0) {
550 regs->nip = (unsigned long) &bp->instr[0];
551 atomic_inc(&bp->ref_count);
552 } else if (stepped < 0) {
553 printf("Couldn't single-step %s instruction\n",
554 (IS_RFID(bp->instr[0])? "rfid": "mtmsrd"));
558 #endif
559 insert_cpu_bpts();
561 local_irq_restore(flags);
563 return cmd != 'X' && cmd != EOF;
566 int xmon(struct pt_regs *excp)
568 struct pt_regs regs;
570 if (excp == NULL) {
571 ppc_save_regs(&regs);
572 excp = &regs;
575 return xmon_core(excp, 0);
577 EXPORT_SYMBOL(xmon);
579 irqreturn_t xmon_irq(int irq, void *d)
581 unsigned long flags;
582 local_irq_save(flags);
583 printf("Keyboard interrupt\n");
584 xmon(get_irq_regs());
585 local_irq_restore(flags);
586 return IRQ_HANDLED;
589 static int xmon_bpt(struct pt_regs *regs)
591 struct bpt *bp;
592 unsigned long offset;
594 if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) != (MSR_IR|MSR_64BIT))
595 return 0;
597 /* Are we at the trap at bp->instr[1] for some bp? */
598 bp = in_breakpoint_table(regs->nip, &offset);
599 if (bp != NULL && offset == 4) {
600 regs->nip = bp->address + 4;
601 atomic_dec(&bp->ref_count);
602 return 1;
605 /* Are we at a breakpoint? */
606 bp = at_breakpoint(regs->nip);
607 if (!bp)
608 return 0;
610 xmon_core(regs, 0);
612 return 1;
615 static int xmon_sstep(struct pt_regs *regs)
617 if (user_mode(regs))
618 return 0;
619 xmon_core(regs, 0);
620 return 1;
623 static int xmon_break_match(struct pt_regs *regs)
625 if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) != (MSR_IR|MSR_64BIT))
626 return 0;
627 if (dabr.enabled == 0)
628 return 0;
629 xmon_core(regs, 0);
630 return 1;
633 static int xmon_iabr_match(struct pt_regs *regs)
635 if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) != (MSR_IR|MSR_64BIT))
636 return 0;
637 if (iabr == NULL)
638 return 0;
639 xmon_core(regs, 0);
640 return 1;
643 static int xmon_ipi(struct pt_regs *regs)
645 #ifdef CONFIG_SMP
646 if (in_xmon && !cpumask_test_cpu(smp_processor_id(), &cpus_in_xmon))
647 xmon_core(regs, 1);
648 #endif
649 return 0;
652 static int xmon_fault_handler(struct pt_regs *regs)
654 struct bpt *bp;
655 unsigned long offset;
657 if (in_xmon && catch_memory_errors)
658 handle_fault(regs); /* doesn't return */
660 if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) == (MSR_IR|MSR_64BIT)) {
661 bp = in_breakpoint_table(regs->nip, &offset);
662 if (bp != NULL) {
663 regs->nip = bp->address + offset;
664 atomic_dec(&bp->ref_count);
668 return 0;
671 static struct bpt *at_breakpoint(unsigned long pc)
673 int i;
674 struct bpt *bp;
676 bp = bpts;
677 for (i = 0; i < NBPTS; ++i, ++bp)
678 if (bp->enabled && pc == bp->address)
679 return bp;
680 return NULL;
683 static struct bpt *in_breakpoint_table(unsigned long nip, unsigned long *offp)
685 unsigned long off;
687 off = nip - (unsigned long) bpts;
688 if (off >= sizeof(bpts))
689 return NULL;
690 off %= sizeof(struct bpt);
691 if (off != offsetof(struct bpt, instr[0])
692 && off != offsetof(struct bpt, instr[1]))
693 return NULL;
694 *offp = off - offsetof(struct bpt, instr[0]);
695 return (struct bpt *) (nip - off);
698 static struct bpt *new_breakpoint(unsigned long a)
700 struct bpt *bp;
702 a &= ~3UL;
703 bp = at_breakpoint(a);
704 if (bp)
705 return bp;
707 for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
708 if (!bp->enabled && atomic_read(&bp->ref_count) == 0) {
709 bp->address = a;
710 bp->instr[1] = bpinstr;
711 store_inst(&bp->instr[1]);
712 return bp;
716 printf("Sorry, no free breakpoints. Please clear one first.\n");
717 return NULL;
720 static void insert_bpts(void)
722 int i;
723 struct bpt *bp;
725 bp = bpts;
726 for (i = 0; i < NBPTS; ++i, ++bp) {
727 if ((bp->enabled & (BP_TRAP|BP_IABR)) == 0)
728 continue;
729 if (mread(bp->address, &bp->instr[0], 4) != 4) {
730 printf("Couldn't read instruction at %lx, "
731 "disabling breakpoint there\n", bp->address);
732 bp->enabled = 0;
733 continue;
735 if (IS_MTMSRD(bp->instr[0]) || IS_RFID(bp->instr[0])) {
736 printf("Breakpoint at %lx is on an mtmsrd or rfid "
737 "instruction, disabling it\n", bp->address);
738 bp->enabled = 0;
739 continue;
741 store_inst(&bp->instr[0]);
742 if (bp->enabled & BP_IABR)
743 continue;
744 if (mwrite(bp->address, &bpinstr, 4) != 4) {
745 printf("Couldn't write instruction at %lx, "
746 "disabling breakpoint there\n", bp->address);
747 bp->enabled &= ~BP_TRAP;
748 continue;
750 store_inst((void *)bp->address);
754 static void insert_cpu_bpts(void)
756 struct arch_hw_breakpoint brk;
758 if (dabr.enabled) {
759 brk.address = dabr.address;
760 brk.type = (dabr.enabled & HW_BRK_TYPE_DABR) | HW_BRK_TYPE_PRIV_ALL;
761 brk.len = 8;
762 __set_breakpoint(&brk);
764 if (iabr && cpu_has_feature(CPU_FTR_IABR))
765 mtspr(SPRN_IABR, iabr->address
766 | (iabr->enabled & (BP_IABR|BP_IABR_TE)));
769 static void remove_bpts(void)
771 int i;
772 struct bpt *bp;
773 unsigned instr;
775 bp = bpts;
776 for (i = 0; i < NBPTS; ++i, ++bp) {
777 if ((bp->enabled & (BP_TRAP|BP_IABR)) != BP_TRAP)
778 continue;
779 if (mread(bp->address, &instr, 4) == 4
780 && instr == bpinstr
781 && mwrite(bp->address, &bp->instr, 4) != 4)
782 printf("Couldn't remove breakpoint at %lx\n",
783 bp->address);
784 else
785 store_inst((void *)bp->address);
789 static void remove_cpu_bpts(void)
791 hw_breakpoint_disable();
792 if (cpu_has_feature(CPU_FTR_IABR))
793 mtspr(SPRN_IABR, 0);
796 /* Command interpreting routine */
797 static char *last_cmd;
799 static int
800 cmds(struct pt_regs *excp)
802 int cmd = 0;
804 last_cmd = NULL;
805 xmon_regs = excp;
807 if (!xmon_no_auto_backtrace) {
808 xmon_no_auto_backtrace = 1;
809 xmon_show_stack(excp->gpr[1], excp->link, excp->nip);
812 for(;;) {
813 #ifdef CONFIG_SMP
814 printf("%x:", smp_processor_id());
815 #endif /* CONFIG_SMP */
816 printf("mon> ");
817 flush_input();
818 termch = 0;
819 cmd = skipbl();
820 if( cmd == '\n' ) {
821 if (last_cmd == NULL)
822 continue;
823 take_input(last_cmd);
824 last_cmd = NULL;
825 cmd = inchar();
827 switch (cmd) {
828 case 'm':
829 cmd = inchar();
830 switch (cmd) {
831 case 'm':
832 case 's':
833 case 'd':
834 memops(cmd);
835 break;
836 case 'l':
837 memlocate();
838 break;
839 case 'z':
840 memzcan();
841 break;
842 case 'i':
843 show_mem(0);
844 break;
845 default:
846 termch = cmd;
847 memex();
849 break;
850 case 'd':
851 dump();
852 break;
853 case 'l':
854 symbol_lookup();
855 break;
856 case 'r':
857 prregs(excp); /* print regs */
858 break;
859 case 'e':
860 excprint(excp);
861 break;
862 case 'S':
863 super_regs();
864 break;
865 case 't':
866 backtrace(excp);
867 break;
868 case 'f':
869 cacheflush();
870 break;
871 case 's':
872 if (do_spu_cmd() == 0)
873 break;
874 if (do_step(excp))
875 return cmd;
876 break;
877 case 'x':
878 case 'X':
879 return cmd;
880 case EOF:
881 printf(" <no input ...>\n");
882 mdelay(2000);
883 return cmd;
884 case '?':
885 xmon_puts(help_string);
886 break;
887 case 'b':
888 bpt_cmds();
889 break;
890 case 'C':
891 csum();
892 break;
893 case 'c':
894 if (cpu_cmd())
895 return 0;
896 break;
897 case 'z':
898 bootcmds();
899 break;
900 case 'p':
901 proccall();
902 break;
903 #ifdef CONFIG_PPC_STD_MMU
904 case 'u':
905 dump_segments();
906 break;
907 #elif defined(CONFIG_4xx)
908 case 'u':
909 dump_tlb_44x();
910 break;
911 #elif defined(CONFIG_PPC_BOOK3E)
912 case 'u':
913 dump_tlb_book3e();
914 break;
915 #endif
916 default:
917 printf("Unrecognized command: ");
918 do {
919 if (' ' < cmd && cmd <= '~')
920 putchar(cmd);
921 else
922 printf("\\x%x", cmd);
923 cmd = inchar();
924 } while (cmd != '\n');
925 printf(" (type ? for help)\n");
926 break;
931 #ifdef CONFIG_BOOKE
932 static int do_step(struct pt_regs *regs)
934 regs->msr |= MSR_DE;
935 mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) | DBCR0_IC | DBCR0_IDM);
936 return 1;
938 #else
940 * Step a single instruction.
941 * Some instructions we emulate, others we execute with MSR_SE set.
943 static int do_step(struct pt_regs *regs)
945 unsigned int instr;
946 int stepped;
948 /* check we are in 64-bit kernel mode, translation enabled */
949 if ((regs->msr & (MSR_64BIT|MSR_PR|MSR_IR)) == (MSR_64BIT|MSR_IR)) {
950 if (mread(regs->nip, &instr, 4) == 4) {
951 stepped = emulate_step(regs, instr);
952 if (stepped < 0) {
953 printf("Couldn't single-step %s instruction\n",
954 (IS_RFID(instr)? "rfid": "mtmsrd"));
955 return 0;
957 if (stepped > 0) {
958 regs->trap = 0xd00 | (regs->trap & 1);
959 printf("stepped to ");
960 xmon_print_symbol(regs->nip, " ", "\n");
961 ppc_inst_dump(regs->nip, 1, 0);
962 return 0;
966 regs->msr |= MSR_SE;
967 return 1;
969 #endif
971 static void bootcmds(void)
973 int cmd;
975 cmd = inchar();
976 if (cmd == 'r')
977 ppc_md.restart(NULL);
978 else if (cmd == 'h')
979 ppc_md.halt();
980 else if (cmd == 'p')
981 ppc_md.power_off();
984 static int cpu_cmd(void)
986 #ifdef CONFIG_SMP
987 unsigned long cpu, first_cpu, last_cpu;
988 int timeout;
990 if (!scanhex(&cpu)) {
991 /* print cpus waiting or in xmon */
992 printf("cpus stopped:");
993 last_cpu = first_cpu = NR_CPUS;
994 for_each_possible_cpu(cpu) {
995 if (cpumask_test_cpu(cpu, &cpus_in_xmon)) {
996 if (cpu == last_cpu + 1) {
997 last_cpu = cpu;
998 } else {
999 if (last_cpu != first_cpu)
1000 printf("-0x%lx", last_cpu);
1001 last_cpu = first_cpu = cpu;
1002 printf(" 0x%lx", cpu);
1006 if (last_cpu != first_cpu)
1007 printf("-0x%lx", last_cpu);
1008 printf("\n");
1009 return 0;
1011 /* try to switch to cpu specified */
1012 if (!cpumask_test_cpu(cpu, &cpus_in_xmon)) {
1013 printf("cpu 0x%x isn't in xmon\n", cpu);
1014 return 0;
1016 xmon_taken = 0;
1017 mb();
1018 xmon_owner = cpu;
1019 timeout = 10000000;
1020 while (!xmon_taken) {
1021 if (--timeout == 0) {
1022 if (test_and_set_bit(0, &xmon_taken))
1023 break;
1024 /* take control back */
1025 mb();
1026 xmon_owner = smp_processor_id();
1027 printf("cpu 0x%x didn't take control\n", cpu);
1028 return 0;
1030 barrier();
1032 return 1;
1033 #else
1034 return 0;
1035 #endif /* CONFIG_SMP */
1038 static unsigned short fcstab[256] = {
1039 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
1040 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
1041 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
1042 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
1043 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
1044 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
1045 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
1046 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
1047 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
1048 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
1049 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
1050 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
1051 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
1052 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
1053 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
1054 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
1055 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
1056 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
1057 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
1058 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
1059 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
1060 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
1061 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
1062 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
1063 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
1064 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
1065 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
1066 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
1067 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
1068 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
1069 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
1070 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
1073 #define FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
1075 static void
1076 csum(void)
1078 unsigned int i;
1079 unsigned short fcs;
1080 unsigned char v;
1082 if (!scanhex(&adrs))
1083 return;
1084 if (!scanhex(&ncsum))
1085 return;
1086 fcs = 0xffff;
1087 for (i = 0; i < ncsum; ++i) {
1088 if (mread(adrs+i, &v, 1) == 0) {
1089 printf("csum stopped at "REG"\n", adrs+i);
1090 break;
1092 fcs = FCS(fcs, v);
1094 printf("%x\n", fcs);
1098 * Check if this is a suitable place to put a breakpoint.
1100 static long check_bp_loc(unsigned long addr)
1102 unsigned int instr;
1104 addr &= ~3;
1105 if (!is_kernel_addr(addr)) {
1106 printf("Breakpoints may only be placed at kernel addresses\n");
1107 return 0;
1109 if (!mread(addr, &instr, sizeof(instr))) {
1110 printf("Can't read instruction at address %lx\n", addr);
1111 return 0;
1113 if (IS_MTMSRD(instr) || IS_RFID(instr)) {
1114 printf("Breakpoints may not be placed on mtmsrd or rfid "
1115 "instructions\n");
1116 return 0;
1118 return 1;
1121 static char *breakpoint_help_string =
1122 "Breakpoint command usage:\n"
1123 "b show breakpoints\n"
1124 "b <addr> [cnt] set breakpoint at given instr addr\n"
1125 "bc clear all breakpoints\n"
1126 "bc <n/addr> clear breakpoint number n or at addr\n"
1127 "bi <addr> [cnt] set hardware instr breakpoint (POWER3/RS64 only)\n"
1128 "bd <addr> [cnt] set hardware data breakpoint\n"
1131 static void
1132 bpt_cmds(void)
1134 int cmd;
1135 unsigned long a;
1136 int mode, i;
1137 struct bpt *bp;
1138 const char badaddr[] = "Only kernel addresses are permitted "
1139 "for breakpoints\n";
1141 cmd = inchar();
1142 switch (cmd) {
1143 #ifndef CONFIG_8xx
1144 case 'd': /* bd - hardware data breakpoint */
1145 mode = 7;
1146 cmd = inchar();
1147 if (cmd == 'r')
1148 mode = 5;
1149 else if (cmd == 'w')
1150 mode = 6;
1151 else
1152 termch = cmd;
1153 dabr.address = 0;
1154 dabr.enabled = 0;
1155 if (scanhex(&dabr.address)) {
1156 if (!is_kernel_addr(dabr.address)) {
1157 printf(badaddr);
1158 break;
1160 dabr.address &= ~HW_BRK_TYPE_DABR;
1161 dabr.enabled = mode | BP_DABR;
1163 break;
1165 case 'i': /* bi - hardware instr breakpoint */
1166 if (!cpu_has_feature(CPU_FTR_IABR)) {
1167 printf("Hardware instruction breakpoint "
1168 "not supported on this cpu\n");
1169 break;
1171 if (iabr) {
1172 iabr->enabled &= ~(BP_IABR | BP_IABR_TE);
1173 iabr = NULL;
1175 if (!scanhex(&a))
1176 break;
1177 if (!check_bp_loc(a))
1178 break;
1179 bp = new_breakpoint(a);
1180 if (bp != NULL) {
1181 bp->enabled |= BP_IABR | BP_IABR_TE;
1182 iabr = bp;
1184 break;
1185 #endif
1187 case 'c':
1188 if (!scanhex(&a)) {
1189 /* clear all breakpoints */
1190 for (i = 0; i < NBPTS; ++i)
1191 bpts[i].enabled = 0;
1192 iabr = NULL;
1193 dabr.enabled = 0;
1194 printf("All breakpoints cleared\n");
1195 break;
1198 if (a <= NBPTS && a >= 1) {
1199 /* assume a breakpoint number */
1200 bp = &bpts[a-1]; /* bp nums are 1 based */
1201 } else {
1202 /* assume a breakpoint address */
1203 bp = at_breakpoint(a);
1204 if (bp == NULL) {
1205 printf("No breakpoint at %lx\n", a);
1206 break;
1210 printf("Cleared breakpoint %lx (", BP_NUM(bp));
1211 xmon_print_symbol(bp->address, " ", ")\n");
1212 bp->enabled = 0;
1213 break;
1215 default:
1216 termch = cmd;
1217 cmd = skipbl();
1218 if (cmd == '?') {
1219 printf(breakpoint_help_string);
1220 break;
1222 termch = cmd;
1223 if (!scanhex(&a)) {
1224 /* print all breakpoints */
1225 printf(" type address\n");
1226 if (dabr.enabled) {
1227 printf(" data "REG" [", dabr.address);
1228 if (dabr.enabled & 1)
1229 printf("r");
1230 if (dabr.enabled & 2)
1231 printf("w");
1232 printf("]\n");
1234 for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
1235 if (!bp->enabled)
1236 continue;
1237 printf("%2x %s ", BP_NUM(bp),
1238 (bp->enabled & BP_IABR)? "inst": "trap");
1239 xmon_print_symbol(bp->address, " ", "\n");
1241 break;
1244 if (!check_bp_loc(a))
1245 break;
1246 bp = new_breakpoint(a);
1247 if (bp != NULL)
1248 bp->enabled |= BP_TRAP;
1249 break;
1253 /* Very cheap human name for vector lookup. */
1254 static
1255 const char *getvecname(unsigned long vec)
1257 char *ret;
1259 switch (vec) {
1260 case 0x100: ret = "(System Reset)"; break;
1261 case 0x200: ret = "(Machine Check)"; break;
1262 case 0x300: ret = "(Data Access)"; break;
1263 case 0x380: ret = "(Data SLB Access)"; break;
1264 case 0x400: ret = "(Instruction Access)"; break;
1265 case 0x480: ret = "(Instruction SLB Access)"; break;
1266 case 0x500: ret = "(Hardware Interrupt)"; break;
1267 case 0x600: ret = "(Alignment)"; break;
1268 case 0x700: ret = "(Program Check)"; break;
1269 case 0x800: ret = "(FPU Unavailable)"; break;
1270 case 0x900: ret = "(Decrementer)"; break;
1271 case 0x980: ret = "(Hypervisor Decrementer)"; break;
1272 case 0xa00: ret = "(Doorbell)"; break;
1273 case 0xc00: ret = "(System Call)"; break;
1274 case 0xd00: ret = "(Single Step)"; break;
1275 case 0xe40: ret = "(Emulation Assist)"; break;
1276 case 0xe60: ret = "(HMI)"; break;
1277 case 0xe80: ret = "(Hypervisor Doorbell)"; break;
1278 case 0xf00: ret = "(Performance Monitor)"; break;
1279 case 0xf20: ret = "(Altivec Unavailable)"; break;
1280 case 0x1300: ret = "(Instruction Breakpoint)"; break;
1281 case 0x1500: ret = "(Denormalisation)"; break;
1282 case 0x1700: ret = "(Altivec Assist)"; break;
1283 default: ret = "";
1285 return ret;
1288 static void get_function_bounds(unsigned long pc, unsigned long *startp,
1289 unsigned long *endp)
1291 unsigned long size, offset;
1292 const char *name;
1294 *startp = *endp = 0;
1295 if (pc == 0)
1296 return;
1297 if (setjmp(bus_error_jmp) == 0) {
1298 catch_memory_errors = 1;
1299 sync();
1300 name = kallsyms_lookup(pc, &size, &offset, NULL, tmpstr);
1301 if (name != NULL) {
1302 *startp = pc - offset;
1303 *endp = pc - offset + size;
1305 sync();
1307 catch_memory_errors = 0;
1310 #define LRSAVE_OFFSET (STACK_FRAME_LR_SAVE * sizeof(unsigned long))
1311 #define MARKER_OFFSET (STACK_FRAME_MARKER * sizeof(unsigned long))
1313 static void xmon_show_stack(unsigned long sp, unsigned long lr,
1314 unsigned long pc)
1316 int max_to_print = 64;
1317 unsigned long ip;
1318 unsigned long newsp;
1319 unsigned long marker;
1320 struct pt_regs regs;
1322 while (max_to_print--) {
1323 if (sp < PAGE_OFFSET) {
1324 if (sp != 0)
1325 printf("SP (%lx) is in userspace\n", sp);
1326 break;
1329 if (!mread(sp + LRSAVE_OFFSET, &ip, sizeof(unsigned long))
1330 || !mread(sp, &newsp, sizeof(unsigned long))) {
1331 printf("Couldn't read stack frame at %lx\n", sp);
1332 break;
1336 * For the first stack frame, try to work out if
1337 * LR and/or the saved LR value in the bottommost
1338 * stack frame are valid.
1340 if ((pc | lr) != 0) {
1341 unsigned long fnstart, fnend;
1342 unsigned long nextip;
1343 int printip = 1;
1345 get_function_bounds(pc, &fnstart, &fnend);
1346 nextip = 0;
1347 if (newsp > sp)
1348 mread(newsp + LRSAVE_OFFSET, &nextip,
1349 sizeof(unsigned long));
1350 if (lr == ip) {
1351 if (lr < PAGE_OFFSET
1352 || (fnstart <= lr && lr < fnend))
1353 printip = 0;
1354 } else if (lr == nextip) {
1355 printip = 0;
1356 } else if (lr >= PAGE_OFFSET
1357 && !(fnstart <= lr && lr < fnend)) {
1358 printf("[link register ] ");
1359 xmon_print_symbol(lr, " ", "\n");
1361 if (printip) {
1362 printf("["REG"] ", sp);
1363 xmon_print_symbol(ip, " ", " (unreliable)\n");
1365 pc = lr = 0;
1367 } else {
1368 printf("["REG"] ", sp);
1369 xmon_print_symbol(ip, " ", "\n");
1372 /* Look for "regshere" marker to see if this is
1373 an exception frame. */
1374 if (mread(sp + MARKER_OFFSET, &marker, sizeof(unsigned long))
1375 && marker == STACK_FRAME_REGS_MARKER) {
1376 if (mread(sp + STACK_FRAME_OVERHEAD, &regs, sizeof(regs))
1377 != sizeof(regs)) {
1378 printf("Couldn't read registers at %lx\n",
1379 sp + STACK_FRAME_OVERHEAD);
1380 break;
1382 printf("--- Exception: %lx %s at ", regs.trap,
1383 getvecname(TRAP(&regs)));
1384 pc = regs.nip;
1385 lr = regs.link;
1386 xmon_print_symbol(pc, " ", "\n");
1389 if (newsp == 0)
1390 break;
1392 sp = newsp;
1396 static void backtrace(struct pt_regs *excp)
1398 unsigned long sp;
1400 if (scanhex(&sp))
1401 xmon_show_stack(sp, 0, 0);
1402 else
1403 xmon_show_stack(excp->gpr[1], excp->link, excp->nip);
1404 scannl();
1407 static void print_bug_trap(struct pt_regs *regs)
1409 #ifdef CONFIG_BUG
1410 const struct bug_entry *bug;
1411 unsigned long addr;
1413 if (regs->msr & MSR_PR)
1414 return; /* not in kernel */
1415 addr = regs->nip; /* address of trap instruction */
1416 if (addr < PAGE_OFFSET)
1417 return;
1418 bug = find_bug(regs->nip);
1419 if (bug == NULL)
1420 return;
1421 if (is_warning_bug(bug))
1422 return;
1424 #ifdef CONFIG_DEBUG_BUGVERBOSE
1425 printf("kernel BUG at %s:%u!\n",
1426 bug->file, bug->line);
1427 #else
1428 printf("kernel BUG at %p!\n", (void *)bug->bug_addr);
1429 #endif
1430 #endif /* CONFIG_BUG */
1433 static void excprint(struct pt_regs *fp)
1435 unsigned long trap;
1437 #ifdef CONFIG_SMP
1438 printf("cpu 0x%x: ", smp_processor_id());
1439 #endif /* CONFIG_SMP */
1441 trap = TRAP(fp);
1442 printf("Vector: %lx %s at [%lx]\n", fp->trap, getvecname(trap), fp);
1443 printf(" pc: ");
1444 xmon_print_symbol(fp->nip, ": ", "\n");
1446 printf(" lr: ", fp->link);
1447 xmon_print_symbol(fp->link, ": ", "\n");
1449 printf(" sp: %lx\n", fp->gpr[1]);
1450 printf(" msr: %lx\n", fp->msr);
1452 if (trap == 0x300 || trap == 0x380 || trap == 0x600 || trap == 0x200) {
1453 printf(" dar: %lx\n", fp->dar);
1454 if (trap != 0x380)
1455 printf(" dsisr: %lx\n", fp->dsisr);
1458 printf(" current = 0x%lx\n", current);
1459 #ifdef CONFIG_PPC64
1460 printf(" paca = 0x%lx\t softe: %d\t irq_happened: 0x%02x\n",
1461 local_paca, local_paca->soft_enabled, local_paca->irq_happened);
1462 #endif
1463 if (current) {
1464 printf(" pid = %ld, comm = %s\n",
1465 current->pid, current->comm);
1468 if (trap == 0x700)
1469 print_bug_trap(fp);
1472 static void prregs(struct pt_regs *fp)
1474 int n, trap;
1475 unsigned long base;
1476 struct pt_regs regs;
1478 if (scanhex(&base)) {
1479 if (setjmp(bus_error_jmp) == 0) {
1480 catch_memory_errors = 1;
1481 sync();
1482 regs = *(struct pt_regs *)base;
1483 sync();
1484 __delay(200);
1485 } else {
1486 catch_memory_errors = 0;
1487 printf("*** Error reading registers from "REG"\n",
1488 base);
1489 return;
1491 catch_memory_errors = 0;
1492 fp = &regs;
1495 #ifdef CONFIG_PPC64
1496 if (FULL_REGS(fp)) {
1497 for (n = 0; n < 16; ++n)
1498 printf("R%.2ld = "REG" R%.2ld = "REG"\n",
1499 n, fp->gpr[n], n+16, fp->gpr[n+16]);
1500 } else {
1501 for (n = 0; n < 7; ++n)
1502 printf("R%.2ld = "REG" R%.2ld = "REG"\n",
1503 n, fp->gpr[n], n+7, fp->gpr[n+7]);
1505 #else
1506 for (n = 0; n < 32; ++n) {
1507 printf("R%.2d = %.8x%s", n, fp->gpr[n],
1508 (n & 3) == 3? "\n": " ");
1509 if (n == 12 && !FULL_REGS(fp)) {
1510 printf("\n");
1511 break;
1514 #endif
1515 printf("pc = ");
1516 xmon_print_symbol(fp->nip, " ", "\n");
1517 if (TRAP(fp) != 0xc00 && cpu_has_feature(CPU_FTR_CFAR)) {
1518 printf("cfar= ");
1519 xmon_print_symbol(fp->orig_gpr3, " ", "\n");
1521 printf("lr = ");
1522 xmon_print_symbol(fp->link, " ", "\n");
1523 printf("msr = "REG" cr = %.8lx\n", fp->msr, fp->ccr);
1524 printf("ctr = "REG" xer = "REG" trap = %4lx\n",
1525 fp->ctr, fp->xer, fp->trap);
1526 trap = TRAP(fp);
1527 if (trap == 0x300 || trap == 0x380 || trap == 0x600)
1528 printf("dar = "REG" dsisr = %.8lx\n", fp->dar, fp->dsisr);
1531 static void cacheflush(void)
1533 int cmd;
1534 unsigned long nflush;
1536 cmd = inchar();
1537 if (cmd != 'i')
1538 termch = cmd;
1539 scanhex((void *)&adrs);
1540 if (termch != '\n')
1541 termch = 0;
1542 nflush = 1;
1543 scanhex(&nflush);
1544 nflush = (nflush + L1_CACHE_BYTES - 1) / L1_CACHE_BYTES;
1545 if (setjmp(bus_error_jmp) == 0) {
1546 catch_memory_errors = 1;
1547 sync();
1549 if (cmd != 'i') {
1550 for (; nflush > 0; --nflush, adrs += L1_CACHE_BYTES)
1551 cflush((void *) adrs);
1552 } else {
1553 for (; nflush > 0; --nflush, adrs += L1_CACHE_BYTES)
1554 cinval((void *) adrs);
1556 sync();
1557 /* wait a little while to see if we get a machine check */
1558 __delay(200);
1560 catch_memory_errors = 0;
1563 static unsigned long
1564 read_spr(int n)
1566 unsigned int instrs[2];
1567 unsigned long (*code)(void);
1568 unsigned long ret = -1UL;
1569 #ifdef CONFIG_PPC64
1570 unsigned long opd[3];
1572 opd[0] = (unsigned long)instrs;
1573 opd[1] = 0;
1574 opd[2] = 0;
1575 code = (unsigned long (*)(void)) opd;
1576 #else
1577 code = (unsigned long (*)(void)) instrs;
1578 #endif
1580 /* mfspr r3,n; blr */
1581 instrs[0] = 0x7c6002a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
1582 instrs[1] = 0x4e800020;
1583 store_inst(instrs);
1584 store_inst(instrs+1);
1586 if (setjmp(bus_error_jmp) == 0) {
1587 catch_memory_errors = 1;
1588 sync();
1590 ret = code();
1592 sync();
1593 /* wait a little while to see if we get a machine check */
1594 __delay(200);
1595 n = size;
1598 return ret;
1601 static void
1602 write_spr(int n, unsigned long val)
1604 unsigned int instrs[2];
1605 unsigned long (*code)(unsigned long);
1606 #ifdef CONFIG_PPC64
1607 unsigned long opd[3];
1609 opd[0] = (unsigned long)instrs;
1610 opd[1] = 0;
1611 opd[2] = 0;
1612 code = (unsigned long (*)(unsigned long)) opd;
1613 #else
1614 code = (unsigned long (*)(unsigned long)) instrs;
1615 #endif
1617 instrs[0] = 0x7c6003a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
1618 instrs[1] = 0x4e800020;
1619 store_inst(instrs);
1620 store_inst(instrs+1);
1622 if (setjmp(bus_error_jmp) == 0) {
1623 catch_memory_errors = 1;
1624 sync();
1626 code(val);
1628 sync();
1629 /* wait a little while to see if we get a machine check */
1630 __delay(200);
1631 n = size;
1635 static unsigned long regno;
1636 extern char exc_prolog;
1637 extern char dec_exc;
1639 static void super_regs(void)
1641 int cmd;
1642 unsigned long val;
1644 cmd = skipbl();
1645 if (cmd == '\n') {
1646 unsigned long sp, toc;
1647 asm("mr %0,1" : "=r" (sp) :);
1648 asm("mr %0,2" : "=r" (toc) :);
1650 printf("msr = "REG" sprg0= "REG"\n",
1651 mfmsr(), mfspr(SPRN_SPRG0));
1652 printf("pvr = "REG" sprg1= "REG"\n",
1653 mfspr(SPRN_PVR), mfspr(SPRN_SPRG1));
1654 printf("dec = "REG" sprg2= "REG"\n",
1655 mfspr(SPRN_DEC), mfspr(SPRN_SPRG2));
1656 printf("sp = "REG" sprg3= "REG"\n", sp, mfspr(SPRN_SPRG3));
1657 printf("toc = "REG" dar = "REG"\n", toc, mfspr(SPRN_DAR));
1659 return;
1662 scanhex(&regno);
1663 switch (cmd) {
1664 case 'w':
1665 val = read_spr(regno);
1666 scanhex(&val);
1667 write_spr(regno, val);
1668 /* fall through */
1669 case 'r':
1670 printf("spr %lx = %lx\n", regno, read_spr(regno));
1671 break;
1673 scannl();
1677 * Stuff for reading and writing memory safely
1679 static int
1680 mread(unsigned long adrs, void *buf, int size)
1682 volatile int n;
1683 char *p, *q;
1685 n = 0;
1686 if (setjmp(bus_error_jmp) == 0) {
1687 catch_memory_errors = 1;
1688 sync();
1689 p = (char *)adrs;
1690 q = (char *)buf;
1691 switch (size) {
1692 case 2:
1693 *(u16 *)q = *(u16 *)p;
1694 break;
1695 case 4:
1696 *(u32 *)q = *(u32 *)p;
1697 break;
1698 case 8:
1699 *(u64 *)q = *(u64 *)p;
1700 break;
1701 default:
1702 for( ; n < size; ++n) {
1703 *q++ = *p++;
1704 sync();
1707 sync();
1708 /* wait a little while to see if we get a machine check */
1709 __delay(200);
1710 n = size;
1712 catch_memory_errors = 0;
1713 return n;
1716 static int
1717 mwrite(unsigned long adrs, void *buf, int size)
1719 volatile int n;
1720 char *p, *q;
1722 n = 0;
1723 if (setjmp(bus_error_jmp) == 0) {
1724 catch_memory_errors = 1;
1725 sync();
1726 p = (char *) adrs;
1727 q = (char *) buf;
1728 switch (size) {
1729 case 2:
1730 *(u16 *)p = *(u16 *)q;
1731 break;
1732 case 4:
1733 *(u32 *)p = *(u32 *)q;
1734 break;
1735 case 8:
1736 *(u64 *)p = *(u64 *)q;
1737 break;
1738 default:
1739 for ( ; n < size; ++n) {
1740 *p++ = *q++;
1741 sync();
1744 sync();
1745 /* wait a little while to see if we get a machine check */
1746 __delay(200);
1747 n = size;
1748 } else {
1749 printf("*** Error writing address "REG"\n", adrs + n);
1751 catch_memory_errors = 0;
1752 return n;
1755 static int fault_type;
1756 static int fault_except;
1757 static char *fault_chars[] = { "--", "**", "##" };
1759 static int handle_fault(struct pt_regs *regs)
1761 fault_except = TRAP(regs);
1762 switch (TRAP(regs)) {
1763 case 0x200:
1764 fault_type = 0;
1765 break;
1766 case 0x300:
1767 case 0x380:
1768 fault_type = 1;
1769 break;
1770 default:
1771 fault_type = 2;
1774 longjmp(bus_error_jmp, 1);
1776 return 0;
1779 #define SWAP(a, b, t) ((t) = (a), (a) = (b), (b) = (t))
1781 static void
1782 byterev(unsigned char *val, int size)
1784 int t;
1786 switch (size) {
1787 case 2:
1788 SWAP(val[0], val[1], t);
1789 break;
1790 case 4:
1791 SWAP(val[0], val[3], t);
1792 SWAP(val[1], val[2], t);
1793 break;
1794 case 8: /* is there really any use for this? */
1795 SWAP(val[0], val[7], t);
1796 SWAP(val[1], val[6], t);
1797 SWAP(val[2], val[5], t);
1798 SWAP(val[3], val[4], t);
1799 break;
1803 static int brev;
1804 static int mnoread;
1806 static char *memex_help_string =
1807 "Memory examine command usage:\n"
1808 "m [addr] [flags] examine/change memory\n"
1809 " addr is optional. will start where left off.\n"
1810 " flags may include chars from this set:\n"
1811 " b modify by bytes (default)\n"
1812 " w modify by words (2 byte)\n"
1813 " l modify by longs (4 byte)\n"
1814 " d modify by doubleword (8 byte)\n"
1815 " r toggle reverse byte order mode\n"
1816 " n do not read memory (for i/o spaces)\n"
1817 " . ok to read (default)\n"
1818 "NOTE: flags are saved as defaults\n"
1821 static char *memex_subcmd_help_string =
1822 "Memory examine subcommands:\n"
1823 " hexval write this val to current location\n"
1824 " 'string' write chars from string to this location\n"
1825 " ' increment address\n"
1826 " ^ decrement address\n"
1827 " / increment addr by 0x10. //=0x100, ///=0x1000, etc\n"
1828 " \\ decrement addr by 0x10. \\\\=0x100, \\\\\\=0x1000, etc\n"
1829 " ` clear no-read flag\n"
1830 " ; stay at this addr\n"
1831 " v change to byte mode\n"
1832 " w change to word (2 byte) mode\n"
1833 " l change to long (4 byte) mode\n"
1834 " u change to doubleword (8 byte) mode\n"
1835 " m addr change current addr\n"
1836 " n toggle no-read flag\n"
1837 " r toggle byte reverse flag\n"
1838 " < count back up count bytes\n"
1839 " > count skip forward count bytes\n"
1840 " x exit this mode\n"
1843 static void
1844 memex(void)
1846 int cmd, inc, i, nslash;
1847 unsigned long n;
1848 unsigned char val[16];
1850 scanhex((void *)&adrs);
1851 cmd = skipbl();
1852 if (cmd == '?') {
1853 printf(memex_help_string);
1854 return;
1855 } else {
1856 termch = cmd;
1858 last_cmd = "m\n";
1859 while ((cmd = skipbl()) != '\n') {
1860 switch( cmd ){
1861 case 'b': size = 1; break;
1862 case 'w': size = 2; break;
1863 case 'l': size = 4; break;
1864 case 'd': size = 8; break;
1865 case 'r': brev = !brev; break;
1866 case 'n': mnoread = 1; break;
1867 case '.': mnoread = 0; break;
1870 if( size <= 0 )
1871 size = 1;
1872 else if( size > 8 )
1873 size = 8;
1874 for(;;){
1875 if (!mnoread)
1876 n = mread(adrs, val, size);
1877 printf(REG"%c", adrs, brev? 'r': ' ');
1878 if (!mnoread) {
1879 if (brev)
1880 byterev(val, size);
1881 putchar(' ');
1882 for (i = 0; i < n; ++i)
1883 printf("%.2x", val[i]);
1884 for (; i < size; ++i)
1885 printf("%s", fault_chars[fault_type]);
1887 putchar(' ');
1888 inc = size;
1889 nslash = 0;
1890 for(;;){
1891 if( scanhex(&n) ){
1892 for (i = 0; i < size; ++i)
1893 val[i] = n >> (i * 8);
1894 if (!brev)
1895 byterev(val, size);
1896 mwrite(adrs, val, size);
1897 inc = size;
1899 cmd = skipbl();
1900 if (cmd == '\n')
1901 break;
1902 inc = 0;
1903 switch (cmd) {
1904 case '\'':
1905 for(;;){
1906 n = inchar();
1907 if( n == '\\' )
1908 n = bsesc();
1909 else if( n == '\'' )
1910 break;
1911 for (i = 0; i < size; ++i)
1912 val[i] = n >> (i * 8);
1913 if (!brev)
1914 byterev(val, size);
1915 mwrite(adrs, val, size);
1916 adrs += size;
1918 adrs -= size;
1919 inc = size;
1920 break;
1921 case ',':
1922 adrs += size;
1923 break;
1924 case '.':
1925 mnoread = 0;
1926 break;
1927 case ';':
1928 break;
1929 case 'x':
1930 case EOF:
1931 scannl();
1932 return;
1933 case 'b':
1934 case 'v':
1935 size = 1;
1936 break;
1937 case 'w':
1938 size = 2;
1939 break;
1940 case 'l':
1941 size = 4;
1942 break;
1943 case 'u':
1944 size = 8;
1945 break;
1946 case '^':
1947 adrs -= size;
1948 break;
1949 break;
1950 case '/':
1951 if (nslash > 0)
1952 adrs -= 1 << nslash;
1953 else
1954 nslash = 0;
1955 nslash += 4;
1956 adrs += 1 << nslash;
1957 break;
1958 case '\\':
1959 if (nslash < 0)
1960 adrs += 1 << -nslash;
1961 else
1962 nslash = 0;
1963 nslash -= 4;
1964 adrs -= 1 << -nslash;
1965 break;
1966 case 'm':
1967 scanhex((void *)&adrs);
1968 break;
1969 case 'n':
1970 mnoread = 1;
1971 break;
1972 case 'r':
1973 brev = !brev;
1974 break;
1975 case '<':
1976 n = size;
1977 scanhex(&n);
1978 adrs -= n;
1979 break;
1980 case '>':
1981 n = size;
1982 scanhex(&n);
1983 adrs += n;
1984 break;
1985 case '?':
1986 printf(memex_subcmd_help_string);
1987 break;
1990 adrs += inc;
1994 static int
1995 bsesc(void)
1997 int c;
1999 c = inchar();
2000 switch( c ){
2001 case 'n': c = '\n'; break;
2002 case 'r': c = '\r'; break;
2003 case 'b': c = '\b'; break;
2004 case 't': c = '\t'; break;
2006 return c;
2009 static void xmon_rawdump (unsigned long adrs, long ndump)
2011 long n, m, r, nr;
2012 unsigned char temp[16];
2014 for (n = ndump; n > 0;) {
2015 r = n < 16? n: 16;
2016 nr = mread(adrs, temp, r);
2017 adrs += nr;
2018 for (m = 0; m < r; ++m) {
2019 if (m < nr)
2020 printf("%.2x", temp[m]);
2021 else
2022 printf("%s", fault_chars[fault_type]);
2024 n -= r;
2025 if (nr < r)
2026 break;
2028 printf("\n");
2031 #ifdef CONFIG_PPC64
2032 static void dump_one_paca(int cpu)
2034 struct paca_struct *p;
2036 if (setjmp(bus_error_jmp) != 0) {
2037 printf("*** Error dumping paca for cpu 0x%x!\n", cpu);
2038 return;
2041 catch_memory_errors = 1;
2042 sync();
2044 p = &paca[cpu];
2046 printf("paca for cpu 0x%x @ %p:\n", cpu, p);
2048 printf(" %-*s = %s\n", 16, "possible", cpu_possible(cpu) ? "yes" : "no");
2049 printf(" %-*s = %s\n", 16, "present", cpu_present(cpu) ? "yes" : "no");
2050 printf(" %-*s = %s\n", 16, "online", cpu_online(cpu) ? "yes" : "no");
2052 #define DUMP(paca, name, format) \
2053 printf(" %-*s = %#-*"format"\t(0x%lx)\n", 16, #name, 18, paca->name, \
2054 offsetof(struct paca_struct, name));
2056 DUMP(p, lock_token, "x");
2057 DUMP(p, paca_index, "x");
2058 DUMP(p, kernel_toc, "lx");
2059 DUMP(p, kernelbase, "lx");
2060 DUMP(p, kernel_msr, "lx");
2061 #ifdef CONFIG_PPC_STD_MMU_64
2062 DUMP(p, stab_real, "lx");
2063 DUMP(p, stab_addr, "lx");
2064 #endif
2065 DUMP(p, emergency_sp, "p");
2066 #ifdef CONFIG_PPC_BOOK3S_64
2067 DUMP(p, mc_emergency_sp, "p");
2068 DUMP(p, in_mce, "x");
2069 #endif
2070 DUMP(p, data_offset, "lx");
2071 DUMP(p, hw_cpu_id, "x");
2072 DUMP(p, cpu_start, "x");
2073 DUMP(p, kexec_state, "x");
2074 DUMP(p, __current, "p");
2075 DUMP(p, kstack, "lx");
2076 DUMP(p, stab_rr, "lx");
2077 DUMP(p, saved_r1, "lx");
2078 DUMP(p, trap_save, "x");
2079 DUMP(p, soft_enabled, "x");
2080 DUMP(p, irq_happened, "x");
2081 DUMP(p, io_sync, "x");
2082 DUMP(p, irq_work_pending, "x");
2083 DUMP(p, nap_state_lost, "x");
2085 #undef DUMP
2087 catch_memory_errors = 0;
2088 sync();
2091 static void dump_all_pacas(void)
2093 int cpu;
2095 if (num_possible_cpus() == 0) {
2096 printf("No possible cpus, use 'dp #' to dump individual cpus\n");
2097 return;
2100 for_each_possible_cpu(cpu)
2101 dump_one_paca(cpu);
2104 static void dump_pacas(void)
2106 unsigned long num;
2107 int c;
2109 c = inchar();
2110 if (c == 'a') {
2111 dump_all_pacas();
2112 return;
2115 termch = c; /* Put c back, it wasn't 'a' */
2117 if (scanhex(&num))
2118 dump_one_paca(num);
2119 else
2120 dump_one_paca(xmon_owner);
2122 #endif
2124 #define isxdigit(c) (('0' <= (c) && (c) <= '9') \
2125 || ('a' <= (c) && (c) <= 'f') \
2126 || ('A' <= (c) && (c) <= 'F'))
2127 static void
2128 dump(void)
2130 int c;
2132 c = inchar();
2134 #ifdef CONFIG_PPC64
2135 if (c == 'p') {
2136 dump_pacas();
2137 return;
2139 #endif
2141 if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')
2142 termch = c;
2143 scanhex((void *)&adrs);
2144 if (termch != '\n')
2145 termch = 0;
2146 if (c == 'i') {
2147 scanhex(&nidump);
2148 if (nidump == 0)
2149 nidump = 16;
2150 else if (nidump > MAX_DUMP)
2151 nidump = MAX_DUMP;
2152 adrs += ppc_inst_dump(adrs, nidump, 1);
2153 last_cmd = "di\n";
2154 } else if (c == 'l') {
2155 dump_log_buf();
2156 } else if (c == 'r') {
2157 scanhex(&ndump);
2158 if (ndump == 0)
2159 ndump = 64;
2160 xmon_rawdump(adrs, ndump);
2161 adrs += ndump;
2162 last_cmd = "dr\n";
2163 } else {
2164 scanhex(&ndump);
2165 if (ndump == 0)
2166 ndump = 64;
2167 else if (ndump > MAX_DUMP)
2168 ndump = MAX_DUMP;
2169 prdump(adrs, ndump);
2170 adrs += ndump;
2171 last_cmd = "d\n";
2175 static void
2176 prdump(unsigned long adrs, long ndump)
2178 long n, m, c, r, nr;
2179 unsigned char temp[16];
2181 for (n = ndump; n > 0;) {
2182 printf(REG, adrs);
2183 putchar(' ');
2184 r = n < 16? n: 16;
2185 nr = mread(adrs, temp, r);
2186 adrs += nr;
2187 for (m = 0; m < r; ++m) {
2188 if ((m & (sizeof(long) - 1)) == 0 && m > 0)
2189 putchar(' ');
2190 if (m < nr)
2191 printf("%.2x", temp[m]);
2192 else
2193 printf("%s", fault_chars[fault_type]);
2195 for (; m < 16; ++m) {
2196 if ((m & (sizeof(long) - 1)) == 0)
2197 putchar(' ');
2198 printf(" ");
2200 printf(" |");
2201 for (m = 0; m < r; ++m) {
2202 if (m < nr) {
2203 c = temp[m];
2204 putchar(' ' <= c && c <= '~'? c: '.');
2205 } else
2206 putchar(' ');
2208 n -= r;
2209 for (; m < 16; ++m)
2210 putchar(' ');
2211 printf("|\n");
2212 if (nr < r)
2213 break;
2217 typedef int (*instruction_dump_func)(unsigned long inst, unsigned long addr);
2219 static int
2220 generic_inst_dump(unsigned long adr, long count, int praddr,
2221 instruction_dump_func dump_func)
2223 int nr, dotted;
2224 unsigned long first_adr;
2225 unsigned long inst, last_inst = 0;
2226 unsigned char val[4];
2228 dotted = 0;
2229 for (first_adr = adr; count > 0; --count, adr += 4) {
2230 nr = mread(adr, val, 4);
2231 if (nr == 0) {
2232 if (praddr) {
2233 const char *x = fault_chars[fault_type];
2234 printf(REG" %s%s%s%s\n", adr, x, x, x, x);
2236 break;
2238 inst = GETWORD(val);
2239 if (adr > first_adr && inst == last_inst) {
2240 if (!dotted) {
2241 printf(" ...\n");
2242 dotted = 1;
2244 continue;
2246 dotted = 0;
2247 last_inst = inst;
2248 if (praddr)
2249 printf(REG" %.8x", adr, inst);
2250 printf("\t");
2251 dump_func(inst, adr);
2252 printf("\n");
2254 return adr - first_adr;
2257 static int
2258 ppc_inst_dump(unsigned long adr, long count, int praddr)
2260 return generic_inst_dump(adr, count, praddr, print_insn_powerpc);
2263 void
2264 print_address(unsigned long addr)
2266 xmon_print_symbol(addr, "\t# ", "");
2269 void
2270 dump_log_buf(void)
2272 struct kmsg_dumper dumper = { .active = 1 };
2273 unsigned char buf[128];
2274 size_t len;
2276 if (setjmp(bus_error_jmp) != 0) {
2277 printf("Error dumping printk buffer!\n");
2278 return;
2281 catch_memory_errors = 1;
2282 sync();
2284 kmsg_dump_rewind_nolock(&dumper);
2285 while (kmsg_dump_get_line_nolock(&dumper, false, buf, sizeof(buf), &len)) {
2286 buf[len] = '\0';
2287 printf("%s", buf);
2290 sync();
2291 /* wait a little while to see if we get a machine check */
2292 __delay(200);
2293 catch_memory_errors = 0;
2297 * Memory operations - move, set, print differences
2299 static unsigned long mdest; /* destination address */
2300 static unsigned long msrc; /* source address */
2301 static unsigned long mval; /* byte value to set memory to */
2302 static unsigned long mcount; /* # bytes to affect */
2303 static unsigned long mdiffs; /* max # differences to print */
2305 static void
2306 memops(int cmd)
2308 scanhex((void *)&mdest);
2309 if( termch != '\n' )
2310 termch = 0;
2311 scanhex((void *)(cmd == 's'? &mval: &msrc));
2312 if( termch != '\n' )
2313 termch = 0;
2314 scanhex((void *)&mcount);
2315 switch( cmd ){
2316 case 'm':
2317 memmove((void *)mdest, (void *)msrc, mcount);
2318 break;
2319 case 's':
2320 memset((void *)mdest, mval, mcount);
2321 break;
2322 case 'd':
2323 if( termch != '\n' )
2324 termch = 0;
2325 scanhex((void *)&mdiffs);
2326 memdiffs((unsigned char *)mdest, (unsigned char *)msrc, mcount, mdiffs);
2327 break;
2331 static void
2332 memdiffs(unsigned char *p1, unsigned char *p2, unsigned nb, unsigned maxpr)
2334 unsigned n, prt;
2336 prt = 0;
2337 for( n = nb; n > 0; --n )
2338 if( *p1++ != *p2++ )
2339 if( ++prt <= maxpr )
2340 printf("%.16x %.2x # %.16x %.2x\n", p1 - 1,
2341 p1[-1], p2 - 1, p2[-1]);
2342 if( prt > maxpr )
2343 printf("Total of %d differences\n", prt);
2346 static unsigned mend;
2347 static unsigned mask;
2349 static void
2350 memlocate(void)
2352 unsigned a, n;
2353 unsigned char val[4];
2355 last_cmd = "ml";
2356 scanhex((void *)&mdest);
2357 if (termch != '\n') {
2358 termch = 0;
2359 scanhex((void *)&mend);
2360 if (termch != '\n') {
2361 termch = 0;
2362 scanhex((void *)&mval);
2363 mask = ~0;
2364 if (termch != '\n') termch = 0;
2365 scanhex((void *)&mask);
2368 n = 0;
2369 for (a = mdest; a < mend; a += 4) {
2370 if (mread(a, val, 4) == 4
2371 && ((GETWORD(val) ^ mval) & mask) == 0) {
2372 printf("%.16x: %.16x\n", a, GETWORD(val));
2373 if (++n >= 10)
2374 break;
2379 static unsigned long mskip = 0x1000;
2380 static unsigned long mlim = 0xffffffff;
2382 static void
2383 memzcan(void)
2385 unsigned char v;
2386 unsigned a;
2387 int ok, ook;
2389 scanhex(&mdest);
2390 if (termch != '\n') termch = 0;
2391 scanhex(&mskip);
2392 if (termch != '\n') termch = 0;
2393 scanhex(&mlim);
2394 ook = 0;
2395 for (a = mdest; a < mlim; a += mskip) {
2396 ok = mread(a, &v, 1);
2397 if (ok && !ook) {
2398 printf("%.8x .. ", a);
2399 } else if (!ok && ook)
2400 printf("%.8x\n", a - mskip);
2401 ook = ok;
2402 if (a + mskip < a)
2403 break;
2405 if (ook)
2406 printf("%.8x\n", a - mskip);
2409 static void proccall(void)
2411 unsigned long args[8];
2412 unsigned long ret;
2413 int i;
2414 typedef unsigned long (*callfunc_t)(unsigned long, unsigned long,
2415 unsigned long, unsigned long, unsigned long,
2416 unsigned long, unsigned long, unsigned long);
2417 callfunc_t func;
2419 if (!scanhex(&adrs))
2420 return;
2421 if (termch != '\n')
2422 termch = 0;
2423 for (i = 0; i < 8; ++i)
2424 args[i] = 0;
2425 for (i = 0; i < 8; ++i) {
2426 if (!scanhex(&args[i]) || termch == '\n')
2427 break;
2428 termch = 0;
2430 func = (callfunc_t) adrs;
2431 ret = 0;
2432 if (setjmp(bus_error_jmp) == 0) {
2433 catch_memory_errors = 1;
2434 sync();
2435 ret = func(args[0], args[1], args[2], args[3],
2436 args[4], args[5], args[6], args[7]);
2437 sync();
2438 printf("return value is 0x%lx\n", ret);
2439 } else {
2440 printf("*** %x exception occurred\n", fault_except);
2442 catch_memory_errors = 0;
2445 /* Input scanning routines */
2447 skipbl(void)
2449 int c;
2451 if( termch != 0 ){
2452 c = termch;
2453 termch = 0;
2454 } else
2455 c = inchar();
2456 while( c == ' ' || c == '\t' )
2457 c = inchar();
2458 return c;
2461 #define N_PTREGS 44
2462 static char *regnames[N_PTREGS] = {
2463 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
2464 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
2465 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
2466 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
2467 "pc", "msr", "or3", "ctr", "lr", "xer", "ccr",
2468 #ifdef CONFIG_PPC64
2469 "softe",
2470 #else
2471 "mq",
2472 #endif
2473 "trap", "dar", "dsisr", "res"
2477 scanhex(unsigned long *vp)
2479 int c, d;
2480 unsigned long v;
2482 c = skipbl();
2483 if (c == '%') {
2484 /* parse register name */
2485 char regname[8];
2486 int i;
2488 for (i = 0; i < sizeof(regname) - 1; ++i) {
2489 c = inchar();
2490 if (!isalnum(c)) {
2491 termch = c;
2492 break;
2494 regname[i] = c;
2496 regname[i] = 0;
2497 for (i = 0; i < N_PTREGS; ++i) {
2498 if (strcmp(regnames[i], regname) == 0) {
2499 if (xmon_regs == NULL) {
2500 printf("regs not available\n");
2501 return 0;
2503 *vp = ((unsigned long *)xmon_regs)[i];
2504 return 1;
2507 printf("invalid register name '%%%s'\n", regname);
2508 return 0;
2511 /* skip leading "0x" if any */
2513 if (c == '0') {
2514 c = inchar();
2515 if (c == 'x') {
2516 c = inchar();
2517 } else {
2518 d = hexdigit(c);
2519 if (d == EOF) {
2520 termch = c;
2521 *vp = 0;
2522 return 1;
2525 } else if (c == '$') {
2526 int i;
2527 for (i=0; i<63; i++) {
2528 c = inchar();
2529 if (isspace(c)) {
2530 termch = c;
2531 break;
2533 tmpstr[i] = c;
2535 tmpstr[i++] = 0;
2536 *vp = 0;
2537 if (setjmp(bus_error_jmp) == 0) {
2538 catch_memory_errors = 1;
2539 sync();
2540 *vp = kallsyms_lookup_name(tmpstr);
2541 sync();
2543 catch_memory_errors = 0;
2544 if (!(*vp)) {
2545 printf("unknown symbol '%s'\n", tmpstr);
2546 return 0;
2548 return 1;
2551 d = hexdigit(c);
2552 if (d == EOF) {
2553 termch = c;
2554 return 0;
2556 v = 0;
2557 do {
2558 v = (v << 4) + d;
2559 c = inchar();
2560 d = hexdigit(c);
2561 } while (d != EOF);
2562 termch = c;
2563 *vp = v;
2564 return 1;
2567 static void
2568 scannl(void)
2570 int c;
2572 c = termch;
2573 termch = 0;
2574 while( c != '\n' )
2575 c = inchar();
2578 static int hexdigit(int c)
2580 if( '0' <= c && c <= '9' )
2581 return c - '0';
2582 if( 'A' <= c && c <= 'F' )
2583 return c - ('A' - 10);
2584 if( 'a' <= c && c <= 'f' )
2585 return c - ('a' - 10);
2586 return EOF;
2589 void
2590 getstring(char *s, int size)
2592 int c;
2594 c = skipbl();
2595 do {
2596 if( size > 1 ){
2597 *s++ = c;
2598 --size;
2600 c = inchar();
2601 } while( c != ' ' && c != '\t' && c != '\n' );
2602 termch = c;
2603 *s = 0;
2606 static char line[256];
2607 static char *lineptr;
2609 static void
2610 flush_input(void)
2612 lineptr = NULL;
2615 static int
2616 inchar(void)
2618 if (lineptr == NULL || *lineptr == 0) {
2619 if (xmon_gets(line, sizeof(line)) == NULL) {
2620 lineptr = NULL;
2621 return EOF;
2623 lineptr = line;
2625 return *lineptr++;
2628 static void
2629 take_input(char *str)
2631 lineptr = str;
2635 static void
2636 symbol_lookup(void)
2638 int type = inchar();
2639 unsigned long addr;
2640 static char tmp[64];
2642 switch (type) {
2643 case 'a':
2644 if (scanhex(&addr))
2645 xmon_print_symbol(addr, ": ", "\n");
2646 termch = 0;
2647 break;
2648 case 's':
2649 getstring(tmp, 64);
2650 if (setjmp(bus_error_jmp) == 0) {
2651 catch_memory_errors = 1;
2652 sync();
2653 addr = kallsyms_lookup_name(tmp);
2654 if (addr)
2655 printf("%s: %lx\n", tmp, addr);
2656 else
2657 printf("Symbol '%s' not found.\n", tmp);
2658 sync();
2660 catch_memory_errors = 0;
2661 termch = 0;
2662 break;
2667 /* Print an address in numeric and symbolic form (if possible) */
2668 static void xmon_print_symbol(unsigned long address, const char *mid,
2669 const char *after)
2671 char *modname;
2672 const char *name = NULL;
2673 unsigned long offset, size;
2675 printf(REG, address);
2676 if (setjmp(bus_error_jmp) == 0) {
2677 catch_memory_errors = 1;
2678 sync();
2679 name = kallsyms_lookup(address, &size, &offset, &modname,
2680 tmpstr);
2681 sync();
2682 /* wait a little while to see if we get a machine check */
2683 __delay(200);
2686 catch_memory_errors = 0;
2688 if (name) {
2689 printf("%s%s+%#lx/%#lx", mid, name, offset, size);
2690 if (modname)
2691 printf(" [%s]", modname);
2693 printf("%s", after);
2696 #ifdef CONFIG_PPC_BOOK3S_64
2697 static void dump_slb(void)
2699 int i;
2700 unsigned long esid,vsid,valid;
2701 unsigned long llp;
2703 printf("SLB contents of cpu 0x%x\n", smp_processor_id());
2705 for (i = 0; i < mmu_slb_size; i++) {
2706 asm volatile("slbmfee %0,%1" : "=r" (esid) : "r" (i));
2707 asm volatile("slbmfev %0,%1" : "=r" (vsid) : "r" (i));
2708 valid = (esid & SLB_ESID_V);
2709 if (valid | esid | vsid) {
2710 printf("%02d %016lx %016lx", i, esid, vsid);
2711 if (valid) {
2712 llp = vsid & SLB_VSID_LLP;
2713 if (vsid & SLB_VSID_B_1T) {
2714 printf(" 1T ESID=%9lx VSID=%13lx LLP:%3lx \n",
2715 GET_ESID_1T(esid),
2716 (vsid & ~SLB_VSID_B) >> SLB_VSID_SHIFT_1T,
2717 llp);
2718 } else {
2719 printf(" 256M ESID=%9lx VSID=%13lx LLP:%3lx \n",
2720 GET_ESID(esid),
2721 (vsid & ~SLB_VSID_B) >> SLB_VSID_SHIFT,
2722 llp);
2724 } else
2725 printf("\n");
2730 static void dump_stab(void)
2732 int i;
2733 unsigned long *tmp = (unsigned long *)local_paca->stab_addr;
2735 printf("Segment table contents of cpu 0x%x\n", smp_processor_id());
2737 for (i = 0; i < PAGE_SIZE/16; i++) {
2738 unsigned long a, b;
2740 a = *tmp++;
2741 b = *tmp++;
2743 if (a || b) {
2744 printf("%03d %016lx ", i, a);
2745 printf("%016lx\n", b);
2750 void dump_segments(void)
2752 if (mmu_has_feature(MMU_FTR_SLB))
2753 dump_slb();
2754 else
2755 dump_stab();
2757 #endif
2759 #ifdef CONFIG_PPC_STD_MMU_32
2760 void dump_segments(void)
2762 int i;
2764 printf("sr0-15 =");
2765 for (i = 0; i < 16; ++i)
2766 printf(" %x", mfsrin(i));
2767 printf("\n");
2769 #endif
2771 #ifdef CONFIG_44x
2772 static void dump_tlb_44x(void)
2774 int i;
2776 for (i = 0; i < PPC44x_TLB_SIZE; i++) {
2777 unsigned long w0,w1,w2;
2778 asm volatile("tlbre %0,%1,0" : "=r" (w0) : "r" (i));
2779 asm volatile("tlbre %0,%1,1" : "=r" (w1) : "r" (i));
2780 asm volatile("tlbre %0,%1,2" : "=r" (w2) : "r" (i));
2781 printf("[%02x] %08x %08x %08x ", i, w0, w1, w2);
2782 if (w0 & PPC44x_TLB_VALID) {
2783 printf("V %08x -> %01x%08x %c%c%c%c%c",
2784 w0 & PPC44x_TLB_EPN_MASK,
2785 w1 & PPC44x_TLB_ERPN_MASK,
2786 w1 & PPC44x_TLB_RPN_MASK,
2787 (w2 & PPC44x_TLB_W) ? 'W' : 'w',
2788 (w2 & PPC44x_TLB_I) ? 'I' : 'i',
2789 (w2 & PPC44x_TLB_M) ? 'M' : 'm',
2790 (w2 & PPC44x_TLB_G) ? 'G' : 'g',
2791 (w2 & PPC44x_TLB_E) ? 'E' : 'e');
2793 printf("\n");
2796 #endif /* CONFIG_44x */
2798 #ifdef CONFIG_PPC_BOOK3E
2799 static void dump_tlb_book3e(void)
2801 u32 mmucfg, pidmask, lpidmask;
2802 u64 ramask;
2803 int i, tlb, ntlbs, pidsz, lpidsz, rasz, lrat = 0;
2804 int mmu_version;
2805 static const char *pgsz_names[] = {
2806 " 1K",
2807 " 2K",
2808 " 4K",
2809 " 8K",
2810 " 16K",
2811 " 32K",
2812 " 64K",
2813 "128K",
2814 "256K",
2815 "512K",
2816 " 1M",
2817 " 2M",
2818 " 4M",
2819 " 8M",
2820 " 16M",
2821 " 32M",
2822 " 64M",
2823 "128M",
2824 "256M",
2825 "512M",
2826 " 1G",
2827 " 2G",
2828 " 4G",
2829 " 8G",
2830 " 16G",
2831 " 32G",
2832 " 64G",
2833 "128G",
2834 "256G",
2835 "512G",
2836 " 1T",
2837 " 2T",
2840 /* Gather some infos about the MMU */
2841 mmucfg = mfspr(SPRN_MMUCFG);
2842 mmu_version = (mmucfg & 3) + 1;
2843 ntlbs = ((mmucfg >> 2) & 3) + 1;
2844 pidsz = ((mmucfg >> 6) & 0x1f) + 1;
2845 lpidsz = (mmucfg >> 24) & 0xf;
2846 rasz = (mmucfg >> 16) & 0x7f;
2847 if ((mmu_version > 1) && (mmucfg & 0x10000))
2848 lrat = 1;
2849 printf("Book3E MMU MAV=%d.0,%d TLBs,%d-bit PID,%d-bit LPID,%d-bit RA\n",
2850 mmu_version, ntlbs, pidsz, lpidsz, rasz);
2851 pidmask = (1ul << pidsz) - 1;
2852 lpidmask = (1ul << lpidsz) - 1;
2853 ramask = (1ull << rasz) - 1;
2855 for (tlb = 0; tlb < ntlbs; tlb++) {
2856 u32 tlbcfg;
2857 int nent, assoc, new_cc = 1;
2858 printf("TLB %d:\n------\n", tlb);
2859 switch(tlb) {
2860 case 0:
2861 tlbcfg = mfspr(SPRN_TLB0CFG);
2862 break;
2863 case 1:
2864 tlbcfg = mfspr(SPRN_TLB1CFG);
2865 break;
2866 case 2:
2867 tlbcfg = mfspr(SPRN_TLB2CFG);
2868 break;
2869 case 3:
2870 tlbcfg = mfspr(SPRN_TLB3CFG);
2871 break;
2872 default:
2873 printf("Unsupported TLB number !\n");
2874 continue;
2876 nent = tlbcfg & 0xfff;
2877 assoc = (tlbcfg >> 24) & 0xff;
2878 for (i = 0; i < nent; i++) {
2879 u32 mas0 = MAS0_TLBSEL(tlb);
2880 u32 mas1 = MAS1_TSIZE(BOOK3E_PAGESZ_4K);
2881 u64 mas2 = 0;
2882 u64 mas7_mas3;
2883 int esel = i, cc = i;
2885 if (assoc != 0) {
2886 cc = i / assoc;
2887 esel = i % assoc;
2888 mas2 = cc * 0x1000;
2891 mas0 |= MAS0_ESEL(esel);
2892 mtspr(SPRN_MAS0, mas0);
2893 mtspr(SPRN_MAS1, mas1);
2894 mtspr(SPRN_MAS2, mas2);
2895 asm volatile("tlbre 0,0,0" : : : "memory");
2896 mas1 = mfspr(SPRN_MAS1);
2897 mas2 = mfspr(SPRN_MAS2);
2898 mas7_mas3 = mfspr(SPRN_MAS7_MAS3);
2899 if (assoc && (i % assoc) == 0)
2900 new_cc = 1;
2901 if (!(mas1 & MAS1_VALID))
2902 continue;
2903 if (assoc == 0)
2904 printf("%04x- ", i);
2905 else if (new_cc)
2906 printf("%04x-%c", cc, 'A' + esel);
2907 else
2908 printf(" |%c", 'A' + esel);
2909 new_cc = 0;
2910 printf(" %016llx %04x %s %c%c AS%c",
2911 mas2 & ~0x3ffull,
2912 (mas1 >> 16) & 0x3fff,
2913 pgsz_names[(mas1 >> 7) & 0x1f],
2914 mas1 & MAS1_IND ? 'I' : ' ',
2915 mas1 & MAS1_IPROT ? 'P' : ' ',
2916 mas1 & MAS1_TS ? '1' : '0');
2917 printf(" %c%c%c%c%c%c%c",
2918 mas2 & MAS2_X0 ? 'a' : ' ',
2919 mas2 & MAS2_X1 ? 'v' : ' ',
2920 mas2 & MAS2_W ? 'w' : ' ',
2921 mas2 & MAS2_I ? 'i' : ' ',
2922 mas2 & MAS2_M ? 'm' : ' ',
2923 mas2 & MAS2_G ? 'g' : ' ',
2924 mas2 & MAS2_E ? 'e' : ' ');
2925 printf(" %016llx", mas7_mas3 & ramask & ~0x7ffull);
2926 if (mas1 & MAS1_IND)
2927 printf(" %s\n",
2928 pgsz_names[(mas7_mas3 >> 1) & 0x1f]);
2929 else
2930 printf(" U%c%c%c S%c%c%c\n",
2931 mas7_mas3 & MAS3_UX ? 'x' : ' ',
2932 mas7_mas3 & MAS3_UW ? 'w' : ' ',
2933 mas7_mas3 & MAS3_UR ? 'r' : ' ',
2934 mas7_mas3 & MAS3_SX ? 'x' : ' ',
2935 mas7_mas3 & MAS3_SW ? 'w' : ' ',
2936 mas7_mas3 & MAS3_SR ? 'r' : ' ');
2940 #endif /* CONFIG_PPC_BOOK3E */
2942 static void xmon_init(int enable)
2944 if (enable) {
2945 __debugger = xmon;
2946 __debugger_ipi = xmon_ipi;
2947 __debugger_bpt = xmon_bpt;
2948 __debugger_sstep = xmon_sstep;
2949 __debugger_iabr_match = xmon_iabr_match;
2950 __debugger_break_match = xmon_break_match;
2951 __debugger_fault_handler = xmon_fault_handler;
2952 } else {
2953 __debugger = NULL;
2954 __debugger_ipi = NULL;
2955 __debugger_bpt = NULL;
2956 __debugger_sstep = NULL;
2957 __debugger_iabr_match = NULL;
2958 __debugger_break_match = NULL;
2959 __debugger_fault_handler = NULL;
2963 #ifdef CONFIG_MAGIC_SYSRQ
2964 static void sysrq_handle_xmon(int key)
2966 /* ensure xmon is enabled */
2967 xmon_init(1);
2968 debugger(get_irq_regs());
2971 static struct sysrq_key_op sysrq_xmon_op = {
2972 .handler = sysrq_handle_xmon,
2973 .help_msg = "xmon(x)",
2974 .action_msg = "Entering xmon",
2977 static int __init setup_xmon_sysrq(void)
2979 register_sysrq_key('x', &sysrq_xmon_op);
2980 return 0;
2982 __initcall(setup_xmon_sysrq);
2983 #endif /* CONFIG_MAGIC_SYSRQ */
2985 static int __initdata xmon_early, xmon_off;
2987 static int __init early_parse_xmon(char *p)
2989 if (!p || strncmp(p, "early", 5) == 0) {
2990 /* just "xmon" is equivalent to "xmon=early" */
2991 xmon_init(1);
2992 xmon_early = 1;
2993 } else if (strncmp(p, "on", 2) == 0)
2994 xmon_init(1);
2995 else if (strncmp(p, "off", 3) == 0)
2996 xmon_off = 1;
2997 else if (strncmp(p, "nobt", 4) == 0)
2998 xmon_no_auto_backtrace = 1;
2999 else
3000 return 1;
3002 return 0;
3004 early_param("xmon", early_parse_xmon);
3006 void __init xmon_setup(void)
3008 #ifdef CONFIG_XMON_DEFAULT
3009 if (!xmon_off)
3010 xmon_init(1);
3011 #endif
3012 if (xmon_early)
3013 debugger(NULL);
3016 #ifdef CONFIG_SPU_BASE
3018 struct spu_info {
3019 struct spu *spu;
3020 u64 saved_mfc_sr1_RW;
3021 u32 saved_spu_runcntl_RW;
3022 unsigned long dump_addr;
3023 u8 stopped_ok;
3026 #define XMON_NUM_SPUS 16 /* Enough for current hardware */
3028 static struct spu_info spu_info[XMON_NUM_SPUS];
3030 void xmon_register_spus(struct list_head *list)
3032 struct spu *spu;
3034 list_for_each_entry(spu, list, full_list) {
3035 if (spu->number >= XMON_NUM_SPUS) {
3036 WARN_ON(1);
3037 continue;
3040 spu_info[spu->number].spu = spu;
3041 spu_info[spu->number].stopped_ok = 0;
3042 spu_info[spu->number].dump_addr = (unsigned long)
3043 spu_info[spu->number].spu->local_store;
3047 static void stop_spus(void)
3049 struct spu *spu;
3050 int i;
3051 u64 tmp;
3053 for (i = 0; i < XMON_NUM_SPUS; i++) {
3054 if (!spu_info[i].spu)
3055 continue;
3057 if (setjmp(bus_error_jmp) == 0) {
3058 catch_memory_errors = 1;
3059 sync();
3061 spu = spu_info[i].spu;
3063 spu_info[i].saved_spu_runcntl_RW =
3064 in_be32(&spu->problem->spu_runcntl_RW);
3066 tmp = spu_mfc_sr1_get(spu);
3067 spu_info[i].saved_mfc_sr1_RW = tmp;
3069 tmp &= ~MFC_STATE1_MASTER_RUN_CONTROL_MASK;
3070 spu_mfc_sr1_set(spu, tmp);
3072 sync();
3073 __delay(200);
3075 spu_info[i].stopped_ok = 1;
3077 printf("Stopped spu %.2d (was %s)\n", i,
3078 spu_info[i].saved_spu_runcntl_RW ?
3079 "running" : "stopped");
3080 } else {
3081 catch_memory_errors = 0;
3082 printf("*** Error stopping spu %.2d\n", i);
3084 catch_memory_errors = 0;
3088 static void restart_spus(void)
3090 struct spu *spu;
3091 int i;
3093 for (i = 0; i < XMON_NUM_SPUS; i++) {
3094 if (!spu_info[i].spu)
3095 continue;
3097 if (!spu_info[i].stopped_ok) {
3098 printf("*** Error, spu %d was not successfully stopped"
3099 ", not restarting\n", i);
3100 continue;
3103 if (setjmp(bus_error_jmp) == 0) {
3104 catch_memory_errors = 1;
3105 sync();
3107 spu = spu_info[i].spu;
3108 spu_mfc_sr1_set(spu, spu_info[i].saved_mfc_sr1_RW);
3109 out_be32(&spu->problem->spu_runcntl_RW,
3110 spu_info[i].saved_spu_runcntl_RW);
3112 sync();
3113 __delay(200);
3115 printf("Restarted spu %.2d\n", i);
3116 } else {
3117 catch_memory_errors = 0;
3118 printf("*** Error restarting spu %.2d\n", i);
3120 catch_memory_errors = 0;
3124 #define DUMP_WIDTH 23
3125 #define DUMP_VALUE(format, field, value) \
3126 do { \
3127 if (setjmp(bus_error_jmp) == 0) { \
3128 catch_memory_errors = 1; \
3129 sync(); \
3130 printf(" %-*s = "format"\n", DUMP_WIDTH, \
3131 #field, value); \
3132 sync(); \
3133 __delay(200); \
3134 } else { \
3135 catch_memory_errors = 0; \
3136 printf(" %-*s = *** Error reading field.\n", \
3137 DUMP_WIDTH, #field); \
3139 catch_memory_errors = 0; \
3140 } while (0)
3142 #define DUMP_FIELD(obj, format, field) \
3143 DUMP_VALUE(format, field, obj->field)
3145 static void dump_spu_fields(struct spu *spu)
3147 printf("Dumping spu fields at address %p:\n", spu);
3149 DUMP_FIELD(spu, "0x%x", number);
3150 DUMP_FIELD(spu, "%s", name);
3151 DUMP_FIELD(spu, "0x%lx", local_store_phys);
3152 DUMP_FIELD(spu, "0x%p", local_store);
3153 DUMP_FIELD(spu, "0x%lx", ls_size);
3154 DUMP_FIELD(spu, "0x%x", node);
3155 DUMP_FIELD(spu, "0x%lx", flags);
3156 DUMP_FIELD(spu, "%d", class_0_pending);
3157 DUMP_FIELD(spu, "0x%lx", class_0_dar);
3158 DUMP_FIELD(spu, "0x%lx", class_1_dar);
3159 DUMP_FIELD(spu, "0x%lx", class_1_dsisr);
3160 DUMP_FIELD(spu, "0x%lx", irqs[0]);
3161 DUMP_FIELD(spu, "0x%lx", irqs[1]);
3162 DUMP_FIELD(spu, "0x%lx", irqs[2]);
3163 DUMP_FIELD(spu, "0x%x", slb_replace);
3164 DUMP_FIELD(spu, "%d", pid);
3165 DUMP_FIELD(spu, "0x%p", mm);
3166 DUMP_FIELD(spu, "0x%p", ctx);
3167 DUMP_FIELD(spu, "0x%p", rq);
3168 DUMP_FIELD(spu, "0x%p", timestamp);
3169 DUMP_FIELD(spu, "0x%lx", problem_phys);
3170 DUMP_FIELD(spu, "0x%p", problem);
3171 DUMP_VALUE("0x%x", problem->spu_runcntl_RW,
3172 in_be32(&spu->problem->spu_runcntl_RW));
3173 DUMP_VALUE("0x%x", problem->spu_status_R,
3174 in_be32(&spu->problem->spu_status_R));
3175 DUMP_VALUE("0x%x", problem->spu_npc_RW,
3176 in_be32(&spu->problem->spu_npc_RW));
3177 DUMP_FIELD(spu, "0x%p", priv2);
3178 DUMP_FIELD(spu, "0x%p", pdata);
3182 spu_inst_dump(unsigned long adr, long count, int praddr)
3184 return generic_inst_dump(adr, count, praddr, print_insn_spu);
3187 static void dump_spu_ls(unsigned long num, int subcmd)
3189 unsigned long offset, addr, ls_addr;
3191 if (setjmp(bus_error_jmp) == 0) {
3192 catch_memory_errors = 1;
3193 sync();
3194 ls_addr = (unsigned long)spu_info[num].spu->local_store;
3195 sync();
3196 __delay(200);
3197 } else {
3198 catch_memory_errors = 0;
3199 printf("*** Error: accessing spu info for spu %d\n", num);
3200 return;
3202 catch_memory_errors = 0;
3204 if (scanhex(&offset))
3205 addr = ls_addr + offset;
3206 else
3207 addr = spu_info[num].dump_addr;
3209 if (addr >= ls_addr + LS_SIZE) {
3210 printf("*** Error: address outside of local store\n");
3211 return;
3214 switch (subcmd) {
3215 case 'i':
3216 addr += spu_inst_dump(addr, 16, 1);
3217 last_cmd = "sdi\n";
3218 break;
3219 default:
3220 prdump(addr, 64);
3221 addr += 64;
3222 last_cmd = "sd\n";
3223 break;
3226 spu_info[num].dump_addr = addr;
3229 static int do_spu_cmd(void)
3231 static unsigned long num = 0;
3232 int cmd, subcmd = 0;
3234 cmd = inchar();
3235 switch (cmd) {
3236 case 's':
3237 stop_spus();
3238 break;
3239 case 'r':
3240 restart_spus();
3241 break;
3242 case 'd':
3243 subcmd = inchar();
3244 if (isxdigit(subcmd) || subcmd == '\n')
3245 termch = subcmd;
3246 case 'f':
3247 scanhex(&num);
3248 if (num >= XMON_NUM_SPUS || !spu_info[num].spu) {
3249 printf("*** Error: invalid spu number\n");
3250 return 0;
3253 switch (cmd) {
3254 case 'f':
3255 dump_spu_fields(spu_info[num].spu);
3256 break;
3257 default:
3258 dump_spu_ls(num, subcmd);
3259 break;
3262 break;
3263 default:
3264 return -1;
3267 return 0;
3269 #else /* ! CONFIG_SPU_BASE */
3270 static int do_spu_cmd(void)
3272 return -1;
3274 #endif