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