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