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