1
2
3
4
5
6
7
8
9
10
11
12
13
14#include <linux/kernel.h>
15#include <linux/errno.h>
16#include <linux/sched/signal.h>
17#include <linux/smp.h>
18#include <linux/mm.h>
19#include <linux/reboot.h>
20#include <linux/delay.h>
21#include <linux/kallsyms.h>
22#include <linux/kmsg_dump.h>
23#include <linux/cpumask.h>
24#include <linux/export.h>
25#include <linux/sysrq.h>
26#include <linux/interrupt.h>
27#include <linux/irq.h>
28#include <linux/bug.h>
29#include <linux/nmi.h>
30#include <linux/ctype.h>
31#include <linux/highmem.h>
32
33#include <asm/debugfs.h>
34#include <asm/ptrace.h>
35#include <asm/smp.h>
36#include <asm/string.h>
37#include <asm/prom.h>
38#include <asm/machdep.h>
39#include <asm/xmon.h>
40#include <asm/processor.h>
41#include <asm/pgtable.h>
42#include <asm/mmu.h>
43#include <asm/mmu_context.h>
44#include <asm/plpar_wrappers.h>
45#include <asm/cputable.h>
46#include <asm/rtas.h>
47#include <asm/sstep.h>
48#include <asm/irq_regs.h>
49#include <asm/spu.h>
50#include <asm/spu_priv1.h>
51#include <asm/setjmp.h>
52#include <asm/reg.h>
53#include <asm/debug.h>
54#include <asm/hw_breakpoint.h>
55#include <asm/xive.h>
56#include <asm/opal.h>
57#include <asm/firmware.h>
58#include <asm/code-patching.h>
59
60#ifdef CONFIG_PPC64
61#include <asm/hvcall.h>
62#include <asm/paca.h>
63#endif
64
65#include "nonstdio.h"
66#include "dis-asm.h"
67
68#ifdef CONFIG_SMP
69static cpumask_t cpus_in_xmon = CPU_MASK_NONE;
70static unsigned long xmon_taken = 1;
71static int xmon_owner;
72static int xmon_gate;
73#else
74#define xmon_owner 0
75#endif
76
77static unsigned long in_xmon __read_mostly = 0;
78static int xmon_on = IS_ENABLED(CONFIG_XMON_DEFAULT);
79
80static unsigned long adrs;
81static int size = 1;
82#define MAX_DUMP (128 * 1024)
83static unsigned long ndump = 64;
84static unsigned long nidump = 16;
85static unsigned long ncsum = 4096;
86static int termch;
87static char tmpstr[128];
88static int tracing_enabled;
89
90static long bus_error_jmp[JMP_BUF_LEN];
91static int catch_memory_errors;
92static int catch_spr_faults;
93static long *xmon_fault_jmp[NR_CPUS];
94
95
96struct bpt {
97 unsigned long address;
98 unsigned int instr[2];
99 atomic_t ref_count;
100 int enabled;
101 unsigned long pad;
102};
103
104
105#define BP_CIABR 1
106#define BP_TRAP 2
107#define BP_DABR 4
108
109#define NBPTS 256
110static struct bpt bpts[NBPTS];
111static struct bpt dabr;
112static struct bpt *iabr;
113static unsigned bpinstr = 0x7fe00008;
114
115#define BP_NUM(bp) ((bp) - bpts + 1)
116
117
118static int cmds(struct pt_regs *);
119static int mread(unsigned long, void *, int);
120static int mwrite(unsigned long, void *, int);
121static int handle_fault(struct pt_regs *);
122static void byterev(unsigned char *, int);
123static void memex(void);
124static int bsesc(void);
125static void dump(void);
126static void show_pte(unsigned long);
127static void prdump(unsigned long, long);
128static int ppc_inst_dump(unsigned long, long, int);
129static void dump_log_buf(void);
130
131#ifdef CONFIG_PPC_POWERNV
132static void dump_opal_msglog(void);
133#else
134static inline void dump_opal_msglog(void)
135{
136 printf("Machine is not running OPAL firmware.\n");
137}
138#endif
139
140static void backtrace(struct pt_regs *);
141static void excprint(struct pt_regs *);
142static void prregs(struct pt_regs *);
143static void memops(int);
144static void memlocate(void);
145static void memzcan(void);
146static void memdiffs(unsigned char *, unsigned char *, unsigned, unsigned);
147int skipbl(void);
148int scanhex(unsigned long *valp);
149static void scannl(void);
150static int hexdigit(int);
151void getstring(char *, int);
152static void flush_input(void);
153static int inchar(void);
154static void take_input(char *);
155static int read_spr(int, unsigned long *);
156static void write_spr(int, unsigned long);
157static void super_regs(void);
158static void remove_bpts(void);
159static void insert_bpts(void);
160static void remove_cpu_bpts(void);
161static void insert_cpu_bpts(void);
162static struct bpt *at_breakpoint(unsigned long pc);
163static struct bpt *in_breakpoint_table(unsigned long pc, unsigned long *offp);
164static int do_step(struct pt_regs *);
165static void bpt_cmds(void);
166static void cacheflush(void);
167static int cpu_cmd(void);
168static void csum(void);
169static void bootcmds(void);
170static void proccall(void);
171static void show_tasks(void);
172void dump_segments(void);
173static void symbol_lookup(void);
174static void xmon_show_stack(unsigned long sp, unsigned long lr,
175 unsigned long pc);
176static void xmon_print_symbol(unsigned long address, const char *mid,
177 const char *after);
178static const char *getvecname(unsigned long vec);
179
180static int do_spu_cmd(void);
181
182#ifdef CONFIG_44x
183static void dump_tlb_44x(void);
184#endif
185#ifdef CONFIG_PPC_BOOK3E
186static void dump_tlb_book3e(void);
187#endif
188
189#ifdef CONFIG_PPC64
190#define REG "%.16lx"
191#else
192#define REG "%.8lx"
193#endif
194
195#ifdef __LITTLE_ENDIAN__
196#define GETWORD(v) (((v)[3] << 24) + ((v)[2] << 16) + ((v)[1] << 8) + (v)[0])
197#else
198#define GETWORD(v) (((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
199#endif
200
201static char *help_string = "\
202Commands:\n\
203 b show breakpoints\n\
204 bd set data breakpoint\n\
205 bi set instruction breakpoint\n\
206 bc clear breakpoint\n"
207#ifdef CONFIG_SMP
208 "\
209 c print cpus stopped in xmon\n\
210 c# try to switch to cpu number h (in hex)\n"
211#endif
212 "\
213 C checksum\n\
214 d dump bytes\n\
215 d1 dump 1 byte values\n\
216 d2 dump 2 byte values\n\
217 d4 dump 4 byte values\n\
218 d8 dump 8 byte values\n\
219 di dump instructions\n\
220 df dump float values\n\
221 dd dump double values\n\
222 dl dump the kernel log buffer\n"
223#ifdef CONFIG_PPC_POWERNV
224 "\
225 do dump the OPAL message log\n"
226#endif
227#ifdef CONFIG_PPC64
228 "\
229 dp[#] dump paca for current cpu, or cpu #\n\
230 dpa dump paca for all possible cpus\n"
231#endif
232 "\
233 dr dump stream of raw bytes\n\
234 dv dump virtual address translation \n\
235 dt dump the tracing buffers (uses printk)\n\
236 dtc dump the tracing buffers for current CPU (uses printk)\n\
237"
238#ifdef CONFIG_PPC_POWERNV
239" dx# dump xive on CPU #\n\
240 dxi# dump xive irq state #\n\
241 dxa dump xive on all CPUs\n"
242#endif
243" e print exception information\n\
244 f flush cache\n\
245 la lookup symbol+offset of specified address\n\
246 ls lookup address of specified symbol\n\
247 m examine/change memory\n\
248 mm move a block of memory\n\
249 ms set a block of memory\n\
250 md compare two blocks of memory\n\
251 ml locate a block of memory\n\
252 mz zero a block of memory\n\
253 mi show information about memory allocation\n\
254 p call a procedure\n\
255 P list processes/tasks\n\
256 r print registers\n\
257 s single step\n"
258#ifdef CONFIG_SPU_BASE
259" ss stop execution on all spus\n\
260 sr restore execution on stopped spus\n\
261 sf # dump spu fields for spu # (in hex)\n\
262 sd # dump spu local store for spu # (in hex)\n\
263 sdi # disassemble spu local store for spu # (in hex)\n"
264#endif
265" S print special registers\n\
266 Sa print all SPRs\n\
267 Sr # read SPR #\n\
268 Sw #v write v to SPR #\n\
269 t print backtrace\n\
270 x exit monitor and recover\n\
271 X exit monitor and don't recover\n"
272#if defined(CONFIG_PPC64) && !defined(CONFIG_PPC_BOOK3E)
273" u dump segment table or SLB\n"
274#elif defined(CONFIG_PPC_STD_MMU_32)
275" u dump segment registers\n"
276#elif defined(CONFIG_44x) || defined(CONFIG_PPC_BOOK3E)
277" u dump TLB\n"
278#endif
279" U show uptime information\n"
280" ? help\n"
281" # n limit output to n lines per page (for dp, dpa, dl)\n"
282" zr reboot\n\
283 zh halt\n"
284;
285
286static struct pt_regs *xmon_regs;
287
288static inline void sync(void)
289{
290 asm volatile("sync; isync");
291}
292
293static inline void store_inst(void *p)
294{
295 asm volatile ("dcbst 0,%0; sync; icbi 0,%0; isync" : : "r" (p));
296}
297
298static inline void cflush(void *p)
299{
300 asm volatile ("dcbf 0,%0; icbi 0,%0" : : "r" (p));
301}
302
303static inline void cinval(void *p)
304{
305 asm volatile ("dcbi 0,%0; icbi 0,%0" : : "r" (p));
306}
307
308
309
310
311
312
313
314
315
316
317static void write_ciabr(unsigned long ciabr)
318{
319 if (!cpu_has_feature(CPU_FTR_ARCH_207S))
320 return;
321
322 if (cpu_has_feature(CPU_FTR_HVMODE)) {
323 mtspr(SPRN_CIABR, ciabr);
324 return;
325 }
326 plpar_set_ciabr(ciabr);
327}
328
329
330
331
332
333
334
335
336static void set_ciabr(unsigned long addr)
337{
338 addr &= ~CIABR_PRIV;
339
340 if (cpu_has_feature(CPU_FTR_HVMODE))
341 addr |= CIABR_PRIV_HYPER;
342 else
343 addr |= CIABR_PRIV_SUPER;
344 write_ciabr(addr);
345}
346
347
348
349
350
351
352#define SURVEILLANCE_TOKEN 9000
353
354static inline void disable_surveillance(void)
355{
356#ifdef CONFIG_PPC_PSERIES
357
358 static struct rtas_args args;
359 int token;
360
361
362
363
364
365
366
367
368 token = rtas_token("set-indicator");
369 if (token == RTAS_UNKNOWN_SERVICE)
370 return;
371
372 rtas_call_unlocked(&args, token, 3, 1, NULL, SURVEILLANCE_TOKEN, 0, 0);
373
374#endif
375}
376
377#ifdef CONFIG_SMP
378static int xmon_speaker;
379
380static void get_output_lock(void)
381{
382 int me = smp_processor_id() + 0x100;
383 int last_speaker = 0, prev;
384 long timeout;
385
386 if (xmon_speaker == me)
387 return;
388
389 for (;;) {
390 last_speaker = cmpxchg(&xmon_speaker, 0, me);
391 if (last_speaker == 0)
392 return;
393
394
395
396
397
398 timeout = 10000;
399 while (xmon_speaker == last_speaker) {
400 if (--timeout > 0) {
401 udelay(100);
402 continue;
403 }
404
405
406 prev = cmpxchg(&xmon_speaker, last_speaker, me);
407 if (prev == last_speaker)
408 return;
409 break;
410 }
411 }
412}
413
414static void release_output_lock(void)
415{
416 xmon_speaker = 0;
417}
418
419int cpus_are_in_xmon(void)
420{
421 return !cpumask_empty(&cpus_in_xmon);
422}
423
424static bool wait_for_other_cpus(int ncpus)
425{
426 unsigned long timeout;
427
428
429 for (timeout = 20000; timeout != 0; --timeout) {
430 if (cpumask_weight(&cpus_in_xmon) >= ncpus)
431 return true;
432 udelay(100);
433 barrier();
434 }
435
436 return false;
437}
438#endif
439
440static inline int unrecoverable_excp(struct pt_regs *regs)
441{
442#if defined(CONFIG_4xx) || defined(CONFIG_PPC_BOOK3E)
443
444 return 0;
445#else
446 return ((regs->msr & MSR_RI) == 0);
447#endif
448}
449
450static int xmon_core(struct pt_regs *regs, int fromipi)
451{
452 int cmd = 0;
453 struct bpt *bp;
454 long recurse_jmp[JMP_BUF_LEN];
455 unsigned long offset;
456 unsigned long flags;
457#ifdef CONFIG_SMP
458 int cpu;
459 int secondary;
460#endif
461
462 local_irq_save(flags);
463 hard_irq_disable();
464
465 tracing_enabled = tracing_is_on();
466 tracing_off();
467
468 bp = in_breakpoint_table(regs->nip, &offset);
469 if (bp != NULL) {
470 regs->nip = bp->address + offset;
471 atomic_dec(&bp->ref_count);
472 }
473
474 remove_cpu_bpts();
475
476#ifdef CONFIG_SMP
477 cpu = smp_processor_id();
478 if (cpumask_test_cpu(cpu, &cpus_in_xmon)) {
479
480
481
482
483 if (catch_spr_faults)
484 longjmp(bus_error_jmp, 1);
485 get_output_lock();
486 excprint(regs);
487 printf("cpu 0x%x: Exception %lx %s in xmon, "
488 "returning to main loop\n",
489 cpu, regs->trap, getvecname(TRAP(regs)));
490 release_output_lock();
491 longjmp(xmon_fault_jmp[cpu], 1);
492 }
493
494 if (setjmp(recurse_jmp) != 0) {
495 if (!in_xmon || !xmon_gate) {
496 get_output_lock();
497 printf("xmon: WARNING: bad recursive fault "
498 "on cpu 0x%x\n", cpu);
499 release_output_lock();
500 goto waiting;
501 }
502 secondary = !(xmon_taken && cpu == xmon_owner);
503 goto cmdloop;
504 }
505
506 xmon_fault_jmp[cpu] = recurse_jmp;
507
508 bp = NULL;
509 if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) == (MSR_IR|MSR_64BIT))
510 bp = at_breakpoint(regs->nip);
511 if (bp || unrecoverable_excp(regs))
512 fromipi = 0;
513
514 if (!fromipi) {
515 get_output_lock();
516 excprint(regs);
517 if (bp) {
518 printf("cpu 0x%x stopped at breakpoint 0x%lx (",
519 cpu, 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 release_output_lock();
526 }
527
528 cpumask_set_cpu(cpu, &cpus_in_xmon);
529
530 waiting:
531 secondary = 1;
532 spin_begin();
533 while (secondary && !xmon_gate) {
534 if (in_xmon == 0) {
535 if (fromipi) {
536 spin_end();
537 goto leave;
538 }
539 secondary = test_and_set_bit(0, &in_xmon);
540 }
541 spin_cpu_relax();
542 touch_nmi_watchdog();
543 }
544 spin_end();
545
546 if (!secondary && !xmon_gate) {
547
548
549 int ncpus = num_online_cpus();
550
551 xmon_owner = cpu;
552 mb();
553 if (ncpus > 1) {
554
555
556
557
558
559
560
561 if (TRAP(regs) != 0x100 || !wait_for_other_cpus(ncpus))
562 smp_send_debugger_break();
563
564 wait_for_other_cpus(ncpus);
565 }
566 remove_bpts();
567 disable_surveillance();
568
569 if (bp || TRAP(regs) == 0xd00)
570 ppc_inst_dump(regs->nip, 1, 0);
571 printf("enter ? for help\n");
572 mb();
573 xmon_gate = 1;
574 barrier();
575 touch_nmi_watchdog();
576 }
577
578 cmdloop:
579 while (in_xmon) {
580 if (secondary) {
581 spin_begin();
582 if (cpu == xmon_owner) {
583 if (!test_and_set_bit(0, &xmon_taken)) {
584 secondary = 0;
585 spin_end();
586 continue;
587 }
588
589 while (cpu == xmon_owner)
590 spin_cpu_relax();
591 }
592 spin_cpu_relax();
593 touch_nmi_watchdog();
594 } else {
595 cmd = cmds(regs);
596 if (cmd != 0) {
597
598 insert_bpts();
599 xmon_gate = 0;
600 wmb();
601 in_xmon = 0;
602 break;
603 }
604
605 secondary = 1;
606 }
607 }
608 leave:
609 cpumask_clear_cpu(cpu, &cpus_in_xmon);
610 xmon_fault_jmp[cpu] = NULL;
611#else
612
613 if (in_xmon) {
614 printf("Exception %lx %s in xmon, returning to main loop\n",
615 regs->trap, getvecname(TRAP(regs)));
616 longjmp(xmon_fault_jmp[0], 1);
617 }
618 if (setjmp(recurse_jmp) == 0) {
619 xmon_fault_jmp[0] = recurse_jmp;
620 in_xmon = 1;
621
622 excprint(regs);
623 bp = at_breakpoint(regs->nip);
624 if (bp) {
625 printf("Stopped at breakpoint %lx (", BP_NUM(bp));
626 xmon_print_symbol(regs->nip, " ", ")\n");
627 }
628 if (unrecoverable_excp(regs))
629 printf("WARNING: exception is not recoverable, "
630 "can't continue\n");
631 remove_bpts();
632 disable_surveillance();
633
634 if (bp || TRAP(regs) == 0xd00)
635 ppc_inst_dump(regs->nip, 1, 0);
636 printf("enter ? for help\n");
637 }
638
639 cmd = cmds(regs);
640
641 insert_bpts();
642 in_xmon = 0;
643#endif
644
645#ifdef CONFIG_BOOKE
646 if (regs->msr & MSR_DE) {
647 bp = at_breakpoint(regs->nip);
648 if (bp != NULL) {
649 regs->nip = (unsigned long) &bp->instr[0];
650 atomic_inc(&bp->ref_count);
651 }
652 }
653#else
654 if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) == (MSR_IR|MSR_64BIT)) {
655 bp = at_breakpoint(regs->nip);
656 if (bp != NULL) {
657 int stepped = emulate_step(regs, bp->instr[0]);
658 if (stepped == 0) {
659 regs->nip = (unsigned long) &bp->instr[0];
660 atomic_inc(&bp->ref_count);
661 } else if (stepped < 0) {
662 printf("Couldn't single-step %s instruction\n",
663 (IS_RFID(bp->instr[0])? "rfid": "mtmsrd"));
664 }
665 }
666 }
667#endif
668 insert_cpu_bpts();
669
670 touch_nmi_watchdog();
671 local_irq_restore(flags);
672
673 return cmd != 'X' && cmd != EOF;
674}
675
676int xmon(struct pt_regs *excp)
677{
678 struct pt_regs regs;
679
680 if (excp == NULL) {
681 ppc_save_regs(®s);
682 excp = ®s;
683 }
684
685 return xmon_core(excp, 0);
686}
687EXPORT_SYMBOL(xmon);
688
689irqreturn_t xmon_irq(int irq, void *d)
690{
691 unsigned long flags;
692 local_irq_save(flags);
693 printf("Keyboard interrupt\n");
694 xmon(get_irq_regs());
695 local_irq_restore(flags);
696 return IRQ_HANDLED;
697}
698
699static int xmon_bpt(struct pt_regs *regs)
700{
701 struct bpt *bp;
702 unsigned long offset;
703
704 if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) != (MSR_IR|MSR_64BIT))
705 return 0;
706
707
708 bp = in_breakpoint_table(regs->nip, &offset);
709 if (bp != NULL && offset == 4) {
710 regs->nip = bp->address + 4;
711 atomic_dec(&bp->ref_count);
712 return 1;
713 }
714
715
716 bp = at_breakpoint(regs->nip);
717 if (!bp)
718 return 0;
719
720 xmon_core(regs, 0);
721
722 return 1;
723}
724
725static int xmon_sstep(struct pt_regs *regs)
726{
727 if (user_mode(regs))
728 return 0;
729 xmon_core(regs, 0);
730 return 1;
731}
732
733static int xmon_break_match(struct pt_regs *regs)
734{
735 if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) != (MSR_IR|MSR_64BIT))
736 return 0;
737 if (dabr.enabled == 0)
738 return 0;
739 xmon_core(regs, 0);
740 return 1;
741}
742
743static int xmon_iabr_match(struct pt_regs *regs)
744{
745 if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) != (MSR_IR|MSR_64BIT))
746 return 0;
747 if (iabr == NULL)
748 return 0;
749 xmon_core(regs, 0);
750 return 1;
751}
752
753static int xmon_ipi(struct pt_regs *regs)
754{
755#ifdef CONFIG_SMP
756 if (in_xmon && !cpumask_test_cpu(smp_processor_id(), &cpus_in_xmon))
757 xmon_core(regs, 1);
758#endif
759 return 0;
760}
761
762static int xmon_fault_handler(struct pt_regs *regs)
763{
764 struct bpt *bp;
765 unsigned long offset;
766
767 if (in_xmon && catch_memory_errors)
768 handle_fault(regs);
769
770 if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) == (MSR_IR|MSR_64BIT)) {
771 bp = in_breakpoint_table(regs->nip, &offset);
772 if (bp != NULL) {
773 regs->nip = bp->address + offset;
774 atomic_dec(&bp->ref_count);
775 }
776 }
777
778 return 0;
779}
780
781static struct bpt *at_breakpoint(unsigned long pc)
782{
783 int i;
784 struct bpt *bp;
785
786 bp = bpts;
787 for (i = 0; i < NBPTS; ++i, ++bp)
788 if (bp->enabled && pc == bp->address)
789 return bp;
790 return NULL;
791}
792
793static struct bpt *in_breakpoint_table(unsigned long nip, unsigned long *offp)
794{
795 unsigned long off;
796
797 off = nip - (unsigned long) bpts;
798 if (off >= sizeof(bpts))
799 return NULL;
800 off %= sizeof(struct bpt);
801 if (off != offsetof(struct bpt, instr[0])
802 && off != offsetof(struct bpt, instr[1]))
803 return NULL;
804 *offp = off - offsetof(struct bpt, instr[0]);
805 return (struct bpt *) (nip - off);
806}
807
808static struct bpt *new_breakpoint(unsigned long a)
809{
810 struct bpt *bp;
811
812 a &= ~3UL;
813 bp = at_breakpoint(a);
814 if (bp)
815 return bp;
816
817 for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
818 if (!bp->enabled && atomic_read(&bp->ref_count) == 0) {
819 bp->address = a;
820 bp->instr[1] = bpinstr;
821 store_inst(&bp->instr[1]);
822 return bp;
823 }
824 }
825
826 printf("Sorry, no free breakpoints. Please clear one first.\n");
827 return NULL;
828}
829
830static void insert_bpts(void)
831{
832 int i;
833 struct bpt *bp;
834
835 bp = bpts;
836 for (i = 0; i < NBPTS; ++i, ++bp) {
837 if ((bp->enabled & (BP_TRAP|BP_CIABR)) == 0)
838 continue;
839 if (mread(bp->address, &bp->instr[0], 4) != 4) {
840 printf("Couldn't read instruction at %lx, "
841 "disabling breakpoint there\n", bp->address);
842 bp->enabled = 0;
843 continue;
844 }
845 if (IS_MTMSRD(bp->instr[0]) || IS_RFID(bp->instr[0])) {
846 printf("Breakpoint at %lx is on an mtmsrd or rfid "
847 "instruction, disabling it\n", bp->address);
848 bp->enabled = 0;
849 continue;
850 }
851 store_inst(&bp->instr[0]);
852 if (bp->enabled & BP_CIABR)
853 continue;
854 if (patch_instruction((unsigned int *)bp->address,
855 bpinstr) != 0) {
856 printf("Couldn't write instruction at %lx, "
857 "disabling breakpoint there\n", bp->address);
858 bp->enabled &= ~BP_TRAP;
859 continue;
860 }
861 store_inst((void *)bp->address);
862 }
863}
864
865static void insert_cpu_bpts(void)
866{
867 struct arch_hw_breakpoint brk;
868
869 if (dabr.enabled) {
870 brk.address = dabr.address;
871 brk.type = (dabr.enabled & HW_BRK_TYPE_DABR) | HW_BRK_TYPE_PRIV_ALL;
872 brk.len = 8;
873 __set_breakpoint(&brk);
874 }
875
876 if (iabr)
877 set_ciabr(iabr->address);
878}
879
880static void remove_bpts(void)
881{
882 int i;
883 struct bpt *bp;
884 unsigned instr;
885
886 bp = bpts;
887 for (i = 0; i < NBPTS; ++i, ++bp) {
888 if ((bp->enabled & (BP_TRAP|BP_CIABR)) != BP_TRAP)
889 continue;
890 if (mread(bp->address, &instr, 4) == 4
891 && instr == bpinstr
892 && patch_instruction(
893 (unsigned int *)bp->address, bp->instr[0]) != 0)
894 printf("Couldn't remove breakpoint at %lx\n",
895 bp->address);
896 else
897 store_inst((void *)bp->address);
898 }
899}
900
901static void remove_cpu_bpts(void)
902{
903 hw_breakpoint_disable();
904 write_ciabr(0);
905}
906
907
908static void
909show_uptime(void)
910{
911 struct timespec uptime;
912
913 if (setjmp(bus_error_jmp) == 0) {
914 catch_memory_errors = 1;
915 sync();
916
917 get_monotonic_boottime(&uptime);
918 printf("Uptime: %lu.%.2lu seconds\n", (unsigned long)uptime.tv_sec,
919 ((unsigned long)uptime.tv_nsec / (NSEC_PER_SEC/100)));
920
921 sync();
922 __delay(200); \
923 }
924 catch_memory_errors = 0;
925}
926
927static void set_lpp_cmd(void)
928{
929 unsigned long lpp;
930
931 if (!scanhex(&lpp)) {
932 printf("Invalid number.\n");
933 lpp = 0;
934 }
935 xmon_set_pagination_lpp(lpp);
936}
937
938static char *last_cmd;
939
940static int
941cmds(struct pt_regs *excp)
942{
943 int cmd = 0;
944
945 last_cmd = NULL;
946 xmon_regs = excp;
947
948 xmon_show_stack(excp->gpr[1], excp->link, excp->nip);
949
950 for(;;) {
951#ifdef CONFIG_SMP
952 printf("%x:", smp_processor_id());
953#endif
954 printf("mon> ");
955 flush_input();
956 termch = 0;
957 cmd = skipbl();
958 if( cmd == '\n' ) {
959 if (last_cmd == NULL)
960 continue;
961 take_input(last_cmd);
962 last_cmd = NULL;
963 cmd = inchar();
964 }
965 switch (cmd) {
966 case 'm':
967 cmd = inchar();
968 switch (cmd) {
969 case 'm':
970 case 's':
971 case 'd':
972 memops(cmd);
973 break;
974 case 'l':
975 memlocate();
976 break;
977 case 'z':
978 memzcan();
979 break;
980 case 'i':
981 show_mem(0, NULL);
982 break;
983 default:
984 termch = cmd;
985 memex();
986 }
987 break;
988 case 'd':
989 dump();
990 break;
991 case 'l':
992 symbol_lookup();
993 break;
994 case 'r':
995 prregs(excp);
996 break;
997 case 'e':
998 excprint(excp);
999 break;
1000 case 'S':
1001 super_regs();
1002 break;
1003 case 't':
1004 backtrace(excp);
1005 break;
1006 case 'f':
1007 cacheflush();
1008 break;
1009 case 's':
1010 if (do_spu_cmd() == 0)
1011 break;
1012 if (do_step(excp))
1013 return cmd;
1014 break;
1015 case 'x':
1016 case 'X':
1017 if (tracing_enabled)
1018 tracing_on();
1019 return cmd;
1020 case EOF:
1021 printf(" <no input ...>\n");
1022 mdelay(2000);
1023 return cmd;
1024 case '?':
1025 xmon_puts(help_string);
1026 break;
1027 case '#':
1028 set_lpp_cmd();
1029 break;
1030 case 'b':
1031 bpt_cmds();
1032 break;
1033 case 'C':
1034 csum();
1035 break;
1036 case 'c':
1037 if (cpu_cmd())
1038 return 0;
1039 break;
1040 case 'z':
1041 bootcmds();
1042 break;
1043 case 'p':
1044 proccall();
1045 break;
1046 case 'P':
1047 show_tasks();
1048 break;
1049#ifdef CONFIG_PPC_STD_MMU
1050 case 'u':
1051 dump_segments();
1052 break;
1053#elif defined(CONFIG_44x)
1054 case 'u':
1055 dump_tlb_44x();
1056 break;
1057#elif defined(CONFIG_PPC_BOOK3E)
1058 case 'u':
1059 dump_tlb_book3e();
1060 break;
1061#endif
1062 case 'U':
1063 show_uptime();
1064 break;
1065 default:
1066 printf("Unrecognized command: ");
1067 do {
1068 if (' ' < cmd && cmd <= '~')
1069 putchar(cmd);
1070 else
1071 printf("\\x%x", cmd);
1072 cmd = inchar();
1073 } while (cmd != '\n');
1074 printf(" (type ? for help)\n");
1075 break;
1076 }
1077 }
1078}
1079
1080#ifdef CONFIG_BOOKE
1081static int do_step(struct pt_regs *regs)
1082{
1083 regs->msr |= MSR_DE;
1084 mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) | DBCR0_IC | DBCR0_IDM);
1085 return 1;
1086}
1087#else
1088
1089
1090
1091
1092static int do_step(struct pt_regs *regs)
1093{
1094 unsigned int instr;
1095 int stepped;
1096
1097
1098 if ((regs->msr & (MSR_64BIT|MSR_PR|MSR_IR)) == (MSR_64BIT|MSR_IR)) {
1099 if (mread(regs->nip, &instr, 4) == 4) {
1100 stepped = emulate_step(regs, instr);
1101 if (stepped < 0) {
1102 printf("Couldn't single-step %s instruction\n",
1103 (IS_RFID(instr)? "rfid": "mtmsrd"));
1104 return 0;
1105 }
1106 if (stepped > 0) {
1107 regs->trap = 0xd00 | (regs->trap & 1);
1108 printf("stepped to ");
1109 xmon_print_symbol(regs->nip, " ", "\n");
1110 ppc_inst_dump(regs->nip, 1, 0);
1111 return 0;
1112 }
1113 }
1114 }
1115 regs->msr |= MSR_SE;
1116 return 1;
1117}
1118#endif
1119
1120static void bootcmds(void)
1121{
1122 int cmd;
1123
1124 cmd = inchar();
1125 if (cmd == 'r')
1126 ppc_md.restart(NULL);
1127 else if (cmd == 'h')
1128 ppc_md.halt();
1129 else if (cmd == 'p')
1130 if (pm_power_off)
1131 pm_power_off();
1132}
1133
1134static int cpu_cmd(void)
1135{
1136#ifdef CONFIG_SMP
1137 unsigned long cpu, first_cpu, last_cpu;
1138 int timeout;
1139
1140 if (!scanhex(&cpu)) {
1141
1142 printf("cpus stopped:");
1143 last_cpu = first_cpu = NR_CPUS;
1144 for_each_possible_cpu(cpu) {
1145 if (cpumask_test_cpu(cpu, &cpus_in_xmon)) {
1146 if (cpu == last_cpu + 1) {
1147 last_cpu = cpu;
1148 } else {
1149 if (last_cpu != first_cpu)
1150 printf("-0x%lx", last_cpu);
1151 last_cpu = first_cpu = cpu;
1152 printf(" 0x%lx", cpu);
1153 }
1154 }
1155 }
1156 if (last_cpu != first_cpu)
1157 printf("-0x%lx", last_cpu);
1158 printf("\n");
1159 return 0;
1160 }
1161
1162 if (!cpumask_test_cpu(cpu, &cpus_in_xmon)) {
1163 printf("cpu 0x%x isn't in xmon\n", cpu);
1164 return 0;
1165 }
1166 xmon_taken = 0;
1167 mb();
1168 xmon_owner = cpu;
1169 timeout = 10000000;
1170 while (!xmon_taken) {
1171 if (--timeout == 0) {
1172 if (test_and_set_bit(0, &xmon_taken))
1173 break;
1174
1175 mb();
1176 xmon_owner = smp_processor_id();
1177 printf("cpu 0x%x didn't take control\n", cpu);
1178 return 0;
1179 }
1180 barrier();
1181 }
1182 return 1;
1183#else
1184 return 0;
1185#endif
1186}
1187
1188static unsigned short fcstab[256] = {
1189 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
1190 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
1191 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
1192 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
1193 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
1194 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
1195 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
1196 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
1197 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
1198 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
1199 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
1200 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
1201 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
1202 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
1203 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
1204 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
1205 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
1206 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
1207 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
1208 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
1209 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
1210 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
1211 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
1212 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
1213 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
1214 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
1215 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
1216 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
1217 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
1218 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
1219 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
1220 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
1221};
1222
1223#define FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
1224
1225static void
1226csum(void)
1227{
1228 unsigned int i;
1229 unsigned short fcs;
1230 unsigned char v;
1231
1232 if (!scanhex(&adrs))
1233 return;
1234 if (!scanhex(&ncsum))
1235 return;
1236 fcs = 0xffff;
1237 for (i = 0; i < ncsum; ++i) {
1238 if (mread(adrs+i, &v, 1) == 0) {
1239 printf("csum stopped at "REG"\n", adrs+i);
1240 break;
1241 }
1242 fcs = FCS(fcs, v);
1243 }
1244 printf("%x\n", fcs);
1245}
1246
1247
1248
1249
1250static long check_bp_loc(unsigned long addr)
1251{
1252 unsigned int instr;
1253
1254 addr &= ~3;
1255 if (!is_kernel_addr(addr)) {
1256 printf("Breakpoints may only be placed at kernel addresses\n");
1257 return 0;
1258 }
1259 if (!mread(addr, &instr, sizeof(instr))) {
1260 printf("Can't read instruction at address %lx\n", addr);
1261 return 0;
1262 }
1263 if (IS_MTMSRD(instr) || IS_RFID(instr)) {
1264 printf("Breakpoints may not be placed on mtmsrd or rfid "
1265 "instructions\n");
1266 return 0;
1267 }
1268 return 1;
1269}
1270
1271
1272static inline void force_enable_xmon(void)
1273{
1274
1275 if (!xmon_on) {
1276 printf("xmon: Enabling debugger hooks\n");
1277 xmon_on = 1;
1278 }
1279}
1280
1281static char *breakpoint_help_string =
1282 "Breakpoint command usage:\n"
1283 "b show breakpoints\n"
1284 "b <addr> [cnt] set breakpoint at given instr addr\n"
1285 "bc clear all breakpoints\n"
1286 "bc <n/addr> clear breakpoint number n or at addr\n"
1287 "bi <addr> [cnt] set hardware instr breakpoint (POWER8 only)\n"
1288 "bd <addr> [cnt] set hardware data breakpoint\n"
1289 "";
1290
1291static void
1292bpt_cmds(void)
1293{
1294 int cmd;
1295 unsigned long a;
1296 int i;
1297 struct bpt *bp;
1298
1299 cmd = inchar();
1300 switch (cmd) {
1301#ifndef CONFIG_PPC_8xx
1302 static const char badaddr[] = "Only kernel addresses are permitted for breakpoints\n";
1303 int mode;
1304 case 'd':
1305 if (!ppc_breakpoint_available()) {
1306 printf("Hardware data breakpoint not supported on this cpu\n");
1307 break;
1308 }
1309 mode = 7;
1310 cmd = inchar();
1311 if (cmd == 'r')
1312 mode = 5;
1313 else if (cmd == 'w')
1314 mode = 6;
1315 else
1316 termch = cmd;
1317 dabr.address = 0;
1318 dabr.enabled = 0;
1319 if (scanhex(&dabr.address)) {
1320 if (!is_kernel_addr(dabr.address)) {
1321 printf(badaddr);
1322 break;
1323 }
1324 dabr.address &= ~HW_BRK_TYPE_DABR;
1325 dabr.enabled = mode | BP_DABR;
1326 }
1327
1328 force_enable_xmon();
1329 break;
1330
1331 case 'i':
1332 if (!cpu_has_feature(CPU_FTR_ARCH_207S)) {
1333 printf("Hardware instruction breakpoint "
1334 "not supported on this cpu\n");
1335 break;
1336 }
1337 if (iabr) {
1338 iabr->enabled &= ~BP_CIABR;
1339 iabr = NULL;
1340 }
1341 if (!scanhex(&a))
1342 break;
1343 if (!check_bp_loc(a))
1344 break;
1345 bp = new_breakpoint(a);
1346 if (bp != NULL) {
1347 bp->enabled |= BP_CIABR;
1348 iabr = bp;
1349 force_enable_xmon();
1350 }
1351 break;
1352#endif
1353
1354 case 'c':
1355 if (!scanhex(&a)) {
1356
1357 for (i = 0; i < NBPTS; ++i)
1358 bpts[i].enabled = 0;
1359 iabr = NULL;
1360 dabr.enabled = 0;
1361 printf("All breakpoints cleared\n");
1362 break;
1363 }
1364
1365 if (a <= NBPTS && a >= 1) {
1366
1367 bp = &bpts[a-1];
1368 } else {
1369
1370 bp = at_breakpoint(a);
1371 if (bp == NULL) {
1372 printf("No breakpoint at %lx\n", a);
1373 break;
1374 }
1375 }
1376
1377 printf("Cleared breakpoint %lx (", BP_NUM(bp));
1378 xmon_print_symbol(bp->address, " ", ")\n");
1379 bp->enabled = 0;
1380 break;
1381
1382 default:
1383 termch = cmd;
1384 cmd = skipbl();
1385 if (cmd == '?') {
1386 printf(breakpoint_help_string);
1387 break;
1388 }
1389 termch = cmd;
1390 if (!scanhex(&a)) {
1391
1392 printf(" type address\n");
1393 if (dabr.enabled) {
1394 printf(" data "REG" [", dabr.address);
1395 if (dabr.enabled & 1)
1396 printf("r");
1397 if (dabr.enabled & 2)
1398 printf("w");
1399 printf("]\n");
1400 }
1401 for (bp = bpts; bp < &bpts[NBPTS]; ++bp) {
1402 if (!bp->enabled)
1403 continue;
1404 printf("%2x %s ", BP_NUM(bp),
1405 (bp->enabled & BP_CIABR) ? "inst": "trap");
1406 xmon_print_symbol(bp->address, " ", "\n");
1407 }
1408 break;
1409 }
1410
1411 if (!check_bp_loc(a))
1412 break;
1413 bp = new_breakpoint(a);
1414 if (bp != NULL) {
1415 bp->enabled |= BP_TRAP;
1416 force_enable_xmon();
1417 }
1418 break;
1419 }
1420}
1421
1422
1423static
1424const char *getvecname(unsigned long vec)
1425{
1426 char *ret;
1427
1428 switch (vec) {
1429 case 0x100: ret = "(System Reset)"; break;
1430 case 0x200: ret = "(Machine Check)"; break;
1431 case 0x300: ret = "(Data Access)"; break;
1432 case 0x380:
1433 if (radix_enabled())
1434 ret = "(Data Access Out of Range)";
1435 else
1436 ret = "(Data SLB Access)";
1437 break;
1438 case 0x400: ret = "(Instruction Access)"; break;
1439 case 0x480:
1440 if (radix_enabled())
1441 ret = "(Instruction Access Out of Range)";
1442 else
1443 ret = "(Instruction SLB Access)";
1444 break;
1445 case 0x500: ret = "(Hardware Interrupt)"; break;
1446 case 0x600: ret = "(Alignment)"; break;
1447 case 0x700: ret = "(Program Check)"; break;
1448 case 0x800: ret = "(FPU Unavailable)"; break;
1449 case 0x900: ret = "(Decrementer)"; break;
1450 case 0x980: ret = "(Hypervisor Decrementer)"; break;
1451 case 0xa00: ret = "(Doorbell)"; break;
1452 case 0xc00: ret = "(System Call)"; break;
1453 case 0xd00: ret = "(Single Step)"; break;
1454 case 0xe40: ret = "(Emulation Assist)"; break;
1455 case 0xe60: ret = "(HMI)"; break;
1456 case 0xe80: ret = "(Hypervisor Doorbell)"; break;
1457 case 0xf00: ret = "(Performance Monitor)"; break;
1458 case 0xf20: ret = "(Altivec Unavailable)"; break;
1459 case 0x1300: ret = "(Instruction Breakpoint)"; break;
1460 case 0x1500: ret = "(Denormalisation)"; break;
1461 case 0x1700: ret = "(Altivec Assist)"; break;
1462 default: ret = "";
1463 }
1464 return ret;
1465}
1466
1467static void get_function_bounds(unsigned long pc, unsigned long *startp,
1468 unsigned long *endp)
1469{
1470 unsigned long size, offset;
1471 const char *name;
1472
1473 *startp = *endp = 0;
1474 if (pc == 0)
1475 return;
1476 if (setjmp(bus_error_jmp) == 0) {
1477 catch_memory_errors = 1;
1478 sync();
1479 name = kallsyms_lookup(pc, &size, &offset, NULL, tmpstr);
1480 if (name != NULL) {
1481 *startp = pc - offset;
1482 *endp = pc - offset + size;
1483 }
1484 sync();
1485 }
1486 catch_memory_errors = 0;
1487}
1488
1489#define LRSAVE_OFFSET (STACK_FRAME_LR_SAVE * sizeof(unsigned long))
1490#define MARKER_OFFSET (STACK_FRAME_MARKER * sizeof(unsigned long))
1491
1492static void xmon_show_stack(unsigned long sp, unsigned long lr,
1493 unsigned long pc)
1494{
1495 int max_to_print = 64;
1496 unsigned long ip;
1497 unsigned long newsp;
1498 unsigned long marker;
1499 struct pt_regs regs;
1500
1501 while (max_to_print--) {
1502 if (!is_kernel_addr(sp)) {
1503 if (sp != 0)
1504 printf("SP (%lx) is in userspace\n", sp);
1505 break;
1506 }
1507
1508 if (!mread(sp + LRSAVE_OFFSET, &ip, sizeof(unsigned long))
1509 || !mread(sp, &newsp, sizeof(unsigned long))) {
1510 printf("Couldn't read stack frame at %lx\n", sp);
1511 break;
1512 }
1513
1514
1515
1516
1517
1518
1519 if ((pc | lr) != 0) {
1520 unsigned long fnstart, fnend;
1521 unsigned long nextip;
1522 int printip = 1;
1523
1524 get_function_bounds(pc, &fnstart, &fnend);
1525 nextip = 0;
1526 if (newsp > sp)
1527 mread(newsp + LRSAVE_OFFSET, &nextip,
1528 sizeof(unsigned long));
1529 if (lr == ip) {
1530 if (!is_kernel_addr(lr)
1531 || (fnstart <= lr && lr < fnend))
1532 printip = 0;
1533 } else if (lr == nextip) {
1534 printip = 0;
1535 } else if (is_kernel_addr(lr)
1536 && !(fnstart <= lr && lr < fnend)) {
1537 printf("[link register ] ");
1538 xmon_print_symbol(lr, " ", "\n");
1539 }
1540 if (printip) {
1541 printf("["REG"] ", sp);
1542 xmon_print_symbol(ip, " ", " (unreliable)\n");
1543 }
1544 pc = lr = 0;
1545
1546 } else {
1547 printf("["REG"] ", sp);
1548 xmon_print_symbol(ip, " ", "\n");
1549 }
1550
1551
1552
1553 if (mread(sp + MARKER_OFFSET, &marker, sizeof(unsigned long))
1554 && marker == STACK_FRAME_REGS_MARKER) {
1555 if (mread(sp + STACK_FRAME_OVERHEAD, ®s, sizeof(regs))
1556 != sizeof(regs)) {
1557 printf("Couldn't read registers at %lx\n",
1558 sp + STACK_FRAME_OVERHEAD);
1559 break;
1560 }
1561 printf("--- Exception: %lx %s at ", regs.trap,
1562 getvecname(TRAP(®s)));
1563 pc = regs.nip;
1564 lr = regs.link;
1565 xmon_print_symbol(pc, " ", "\n");
1566 }
1567
1568 if (newsp == 0)
1569 break;
1570
1571 sp = newsp;
1572 }
1573}
1574
1575static void backtrace(struct pt_regs *excp)
1576{
1577 unsigned long sp;
1578
1579 if (scanhex(&sp))
1580 xmon_show_stack(sp, 0, 0);
1581 else
1582 xmon_show_stack(excp->gpr[1], excp->link, excp->nip);
1583 scannl();
1584}
1585
1586static void print_bug_trap(struct pt_regs *regs)
1587{
1588#ifdef CONFIG_BUG
1589 const struct bug_entry *bug;
1590 unsigned long addr;
1591
1592 if (regs->msr & MSR_PR)
1593 return;
1594 addr = regs->nip;
1595 if (!is_kernel_addr(addr))
1596 return;
1597 bug = find_bug(regs->nip);
1598 if (bug == NULL)
1599 return;
1600 if (is_warning_bug(bug))
1601 return;
1602
1603#ifdef CONFIG_DEBUG_BUGVERBOSE
1604 printf("kernel BUG at %s:%u!\n",
1605 bug->file, bug->line);
1606#else
1607 printf("kernel BUG at %px!\n", (void *)bug->bug_addr);
1608#endif
1609#endif
1610}
1611
1612static void excprint(struct pt_regs *fp)
1613{
1614 unsigned long trap;
1615
1616#ifdef CONFIG_SMP
1617 printf("cpu 0x%x: ", smp_processor_id());
1618#endif
1619
1620 trap = TRAP(fp);
1621 printf("Vector: %lx %s at [%lx]\n", fp->trap, getvecname(trap), fp);
1622 printf(" pc: ");
1623 xmon_print_symbol(fp->nip, ": ", "\n");
1624
1625 printf(" lr: ", fp->link);
1626 xmon_print_symbol(fp->link, ": ", "\n");
1627
1628 printf(" sp: %lx\n", fp->gpr[1]);
1629 printf(" msr: %lx\n", fp->msr);
1630
1631 if (trap == 0x300 || trap == 0x380 || trap == 0x600 || trap == 0x200) {
1632 printf(" dar: %lx\n", fp->dar);
1633 if (trap != 0x380)
1634 printf(" dsisr: %lx\n", fp->dsisr);
1635 }
1636
1637 printf(" current = 0x%lx\n", current);
1638#ifdef CONFIG_PPC64
1639 printf(" paca = 0x%lx\t softe: %d\t irq_happened: 0x%02x\n",
1640 local_paca, local_paca->irq_soft_mask, local_paca->irq_happened);
1641#endif
1642 if (current) {
1643 printf(" pid = %ld, comm = %s\n",
1644 current->pid, current->comm);
1645 }
1646
1647 if (trap == 0x700)
1648 print_bug_trap(fp);
1649
1650 printf(linux_banner);
1651}
1652
1653static void prregs(struct pt_regs *fp)
1654{
1655 int n, trap;
1656 unsigned long base;
1657 struct pt_regs regs;
1658
1659 if (scanhex(&base)) {
1660 if (setjmp(bus_error_jmp) == 0) {
1661 catch_memory_errors = 1;
1662 sync();
1663 regs = *(struct pt_regs *)base;
1664 sync();
1665 __delay(200);
1666 } else {
1667 catch_memory_errors = 0;
1668 printf("*** Error reading registers from "REG"\n",
1669 base);
1670 return;
1671 }
1672 catch_memory_errors = 0;
1673 fp = ®s;
1674 }
1675
1676#ifdef CONFIG_PPC64
1677 if (FULL_REGS(fp)) {
1678 for (n = 0; n < 16; ++n)
1679 printf("R%.2ld = "REG" R%.2ld = "REG"\n",
1680 n, fp->gpr[n], n+16, fp->gpr[n+16]);
1681 } else {
1682 for (n = 0; n < 7; ++n)
1683 printf("R%.2ld = "REG" R%.2ld = "REG"\n",
1684 n, fp->gpr[n], n+7, fp->gpr[n+7]);
1685 }
1686#else
1687 for (n = 0; n < 32; ++n) {
1688 printf("R%.2d = %.8x%s", n, fp->gpr[n],
1689 (n & 3) == 3? "\n": " ");
1690 if (n == 12 && !FULL_REGS(fp)) {
1691 printf("\n");
1692 break;
1693 }
1694 }
1695#endif
1696 printf("pc = ");
1697 xmon_print_symbol(fp->nip, " ", "\n");
1698 if (TRAP(fp) != 0xc00 && cpu_has_feature(CPU_FTR_CFAR)) {
1699 printf("cfar= ");
1700 xmon_print_symbol(fp->orig_gpr3, " ", "\n");
1701 }
1702 printf("lr = ");
1703 xmon_print_symbol(fp->link, " ", "\n");
1704 printf("msr = "REG" cr = %.8lx\n", fp->msr, fp->ccr);
1705 printf("ctr = "REG" xer = "REG" trap = %4lx\n",
1706 fp->ctr, fp->xer, fp->trap);
1707 trap = TRAP(fp);
1708 if (trap == 0x300 || trap == 0x380 || trap == 0x600)
1709 printf("dar = "REG" dsisr = %.8lx\n", fp->dar, fp->dsisr);
1710}
1711
1712static void cacheflush(void)
1713{
1714 int cmd;
1715 unsigned long nflush;
1716
1717 cmd = inchar();
1718 if (cmd != 'i')
1719 termch = cmd;
1720 scanhex((void *)&adrs);
1721 if (termch != '\n')
1722 termch = 0;
1723 nflush = 1;
1724 scanhex(&nflush);
1725 nflush = (nflush + L1_CACHE_BYTES - 1) / L1_CACHE_BYTES;
1726 if (setjmp(bus_error_jmp) == 0) {
1727 catch_memory_errors = 1;
1728 sync();
1729
1730 if (cmd != 'i') {
1731 for (; nflush > 0; --nflush, adrs += L1_CACHE_BYTES)
1732 cflush((void *) adrs);
1733 } else {
1734 for (; nflush > 0; --nflush, adrs += L1_CACHE_BYTES)
1735 cinval((void *) adrs);
1736 }
1737 sync();
1738
1739 __delay(200);
1740 }
1741 catch_memory_errors = 0;
1742}
1743
1744extern unsigned long xmon_mfspr(int spr, unsigned long default_value);
1745extern void xmon_mtspr(int spr, unsigned long value);
1746
1747static int
1748read_spr(int n, unsigned long *vp)
1749{
1750 unsigned long ret = -1UL;
1751 int ok = 0;
1752
1753 if (setjmp(bus_error_jmp) == 0) {
1754 catch_spr_faults = 1;
1755 sync();
1756
1757 ret = xmon_mfspr(n, *vp);
1758
1759 sync();
1760 *vp = ret;
1761 ok = 1;
1762 }
1763 catch_spr_faults = 0;
1764
1765 return ok;
1766}
1767
1768static void
1769write_spr(int n, unsigned long val)
1770{
1771 if (setjmp(bus_error_jmp) == 0) {
1772 catch_spr_faults = 1;
1773 sync();
1774
1775 xmon_mtspr(n, val);
1776
1777 sync();
1778 } else {
1779 printf("SPR 0x%03x (%4d) Faulted during write\n", n, n);
1780 }
1781 catch_spr_faults = 0;
1782}
1783
1784static void dump_206_sprs(void)
1785{
1786#ifdef CONFIG_PPC64
1787 if (!cpu_has_feature(CPU_FTR_ARCH_206))
1788 return;
1789
1790
1791
1792 printf("srr0 = %.16lx srr1 = %.16lx dsisr = %.8x\n",
1793 mfspr(SPRN_SRR0), mfspr(SPRN_SRR1), mfspr(SPRN_DSISR));
1794 printf("dscr = %.16lx ppr = %.16lx pir = %.8x\n",
1795 mfspr(SPRN_DSCR), mfspr(SPRN_PPR), mfspr(SPRN_PIR));
1796 printf("amr = %.16lx uamor = %.16lx\n",
1797 mfspr(SPRN_AMR), mfspr(SPRN_UAMOR));
1798
1799 if (!(mfmsr() & MSR_HV))
1800 return;
1801
1802 printf("sdr1 = %.16lx hdar = %.16lx hdsisr = %.8x\n",
1803 mfspr(SPRN_SDR1), mfspr(SPRN_HDAR), mfspr(SPRN_HDSISR));
1804 printf("hsrr0 = %.16lx hsrr1 = %.16lx hdec = %.16lx\n",
1805 mfspr(SPRN_HSRR0), mfspr(SPRN_HSRR1), mfspr(SPRN_HDEC));
1806 printf("lpcr = %.16lx pcr = %.16lx lpidr = %.8x\n",
1807 mfspr(SPRN_LPCR), mfspr(SPRN_PCR), mfspr(SPRN_LPID));
1808 printf("hsprg0 = %.16lx hsprg1 = %.16lx amor = %.16lx\n",
1809 mfspr(SPRN_HSPRG0), mfspr(SPRN_HSPRG1), mfspr(SPRN_AMOR));
1810 printf("dabr = %.16lx dabrx = %.16lx\n",
1811 mfspr(SPRN_DABR), mfspr(SPRN_DABRX));
1812#endif
1813}
1814
1815static void dump_207_sprs(void)
1816{
1817#ifdef CONFIG_PPC64
1818 unsigned long msr;
1819
1820 if (!cpu_has_feature(CPU_FTR_ARCH_207S))
1821 return;
1822
1823 printf("dpdes = %.16lx tir = %.16lx cir = %.8x\n",
1824 mfspr(SPRN_DPDES), mfspr(SPRN_TIR), mfspr(SPRN_CIR));
1825
1826 printf("fscr = %.16lx tar = %.16lx pspb = %.8x\n",
1827 mfspr(SPRN_FSCR), mfspr(SPRN_TAR), mfspr(SPRN_PSPB));
1828
1829 msr = mfmsr();
1830 if (msr & MSR_TM) {
1831
1832 printf("tfhar = %.16lx tfiar = %.16lx texasr = %.16lx\n",
1833 mfspr(SPRN_TFHAR), mfspr(SPRN_TFIAR),
1834 mfspr(SPRN_TEXASR));
1835 }
1836
1837 printf("mmcr0 = %.16lx mmcr1 = %.16lx mmcr2 = %.16lx\n",
1838 mfspr(SPRN_MMCR0), mfspr(SPRN_MMCR1), mfspr(SPRN_MMCR2));
1839 printf("pmc1 = %.8x pmc2 = %.8x pmc3 = %.8x pmc4 = %.8x\n",
1840 mfspr(SPRN_PMC1), mfspr(SPRN_PMC2),
1841 mfspr(SPRN_PMC3), mfspr(SPRN_PMC4));
1842 printf("mmcra = %.16lx siar = %.16lx pmc5 = %.8x\n",
1843 mfspr(SPRN_MMCRA), mfspr(SPRN_SIAR), mfspr(SPRN_PMC5));
1844 printf("sdar = %.16lx sier = %.16lx pmc6 = %.8x\n",
1845 mfspr(SPRN_SDAR), mfspr(SPRN_SIER), mfspr(SPRN_PMC6));
1846 printf("ebbhr = %.16lx ebbrr = %.16lx bescr = %.16lx\n",
1847 mfspr(SPRN_EBBHR), mfspr(SPRN_EBBRR), mfspr(SPRN_BESCR));
1848 printf("iamr = %.16lx\n", mfspr(SPRN_IAMR));
1849
1850 if (!(msr & MSR_HV))
1851 return;
1852
1853 printf("hfscr = %.16lx dhdes = %.16lx rpr = %.16lx\n",
1854 mfspr(SPRN_HFSCR), mfspr(SPRN_DHDES), mfspr(SPRN_RPR));
1855 printf("dawr = %.16lx dawrx = %.16lx ciabr = %.16lx\n",
1856 mfspr(SPRN_DAWR), mfspr(SPRN_DAWRX), mfspr(SPRN_CIABR));
1857#endif
1858}
1859
1860static void dump_300_sprs(void)
1861{
1862#ifdef CONFIG_PPC64
1863 bool hv = mfmsr() & MSR_HV;
1864
1865 if (!cpu_has_feature(CPU_FTR_ARCH_300))
1866 return;
1867
1868 printf("pidr = %.16lx tidr = %.16lx\n",
1869 mfspr(SPRN_PID), mfspr(SPRN_TIDR));
1870 printf("asdr = %.16lx psscr = %.16lx\n",
1871 mfspr(SPRN_ASDR), hv ? mfspr(SPRN_PSSCR)
1872 : mfspr(SPRN_PSSCR_PR));
1873
1874 if (!hv)
1875 return;
1876
1877 printf("ptcr = %.16lx\n",
1878 mfspr(SPRN_PTCR));
1879#endif
1880}
1881
1882static void dump_one_spr(int spr, bool show_unimplemented)
1883{
1884 unsigned long val;
1885
1886 val = 0xdeadbeef;
1887 if (!read_spr(spr, &val)) {
1888 printf("SPR 0x%03x (%4d) Faulted during read\n", spr, spr);
1889 return;
1890 }
1891
1892 if (val == 0xdeadbeef) {
1893
1894 val = 0x0badcafe;
1895 if (!read_spr(spr, &val)) {
1896 printf("SPR 0x%03x (%4d) Faulted during read\n", spr, spr);
1897 return;
1898 }
1899
1900 if (val == 0x0badcafe) {
1901 if (show_unimplemented)
1902 printf("SPR 0x%03x (%4d) Unimplemented\n", spr, spr);
1903 return;
1904 }
1905 }
1906
1907 printf("SPR 0x%03x (%4d) = 0x%lx\n", spr, spr, val);
1908}
1909
1910static void super_regs(void)
1911{
1912 static unsigned long regno;
1913 int cmd;
1914 int spr;
1915
1916 cmd = skipbl();
1917
1918 switch (cmd) {
1919 case '\n': {
1920 unsigned long sp, toc;
1921 asm("mr %0,1" : "=r" (sp) :);
1922 asm("mr %0,2" : "=r" (toc) :);
1923
1924 printf("msr = "REG" sprg0 = "REG"\n",
1925 mfmsr(), mfspr(SPRN_SPRG0));
1926 printf("pvr = "REG" sprg1 = "REG"\n",
1927 mfspr(SPRN_PVR), mfspr(SPRN_SPRG1));
1928 printf("dec = "REG" sprg2 = "REG"\n",
1929 mfspr(SPRN_DEC), mfspr(SPRN_SPRG2));
1930 printf("sp = "REG" sprg3 = "REG"\n", sp, mfspr(SPRN_SPRG3));
1931 printf("toc = "REG" dar = "REG"\n", toc, mfspr(SPRN_DAR));
1932
1933 dump_206_sprs();
1934 dump_207_sprs();
1935 dump_300_sprs();
1936
1937 return;
1938 }
1939 case 'w': {
1940 unsigned long val;
1941 scanhex(®no);
1942 val = 0;
1943 read_spr(regno, &val);
1944 scanhex(&val);
1945 write_spr(regno, val);
1946 dump_one_spr(regno, true);
1947 break;
1948 }
1949 case 'r':
1950 scanhex(®no);
1951 dump_one_spr(regno, true);
1952 break;
1953 case 'a':
1954
1955 for (spr = 1; spr < 1024; ++spr)
1956 dump_one_spr(spr, false);
1957 break;
1958 }
1959
1960 scannl();
1961}
1962
1963
1964
1965
1966static int
1967mread(unsigned long adrs, void *buf, int size)
1968{
1969 volatile int n;
1970 char *p, *q;
1971
1972 n = 0;
1973 if (setjmp(bus_error_jmp) == 0) {
1974 catch_memory_errors = 1;
1975 sync();
1976 p = (char *)adrs;
1977 q = (char *)buf;
1978 switch (size) {
1979 case 2:
1980 *(u16 *)q = *(u16 *)p;
1981 break;
1982 case 4:
1983 *(u32 *)q = *(u32 *)p;
1984 break;
1985 case 8:
1986 *(u64 *)q = *(u64 *)p;
1987 break;
1988 default:
1989 for( ; n < size; ++n) {
1990 *q++ = *p++;
1991 sync();
1992 }
1993 }
1994 sync();
1995
1996 __delay(200);
1997 n = size;
1998 }
1999 catch_memory_errors = 0;
2000 return n;
2001}
2002
2003static int
2004mwrite(unsigned long adrs, void *buf, int size)
2005{
2006 volatile int n;
2007 char *p, *q;
2008
2009 n = 0;
2010 if (setjmp(bus_error_jmp) == 0) {
2011 catch_memory_errors = 1;
2012 sync();
2013 p = (char *) adrs;
2014 q = (char *) buf;
2015 switch (size) {
2016 case 2:
2017 *(u16 *)p = *(u16 *)q;
2018 break;
2019 case 4:
2020 *(u32 *)p = *(u32 *)q;
2021 break;
2022 case 8:
2023 *(u64 *)p = *(u64 *)q;
2024 break;
2025 default:
2026 for ( ; n < size; ++n) {
2027 *p++ = *q++;
2028 sync();
2029 }
2030 }
2031 sync();
2032
2033 __delay(200);
2034 n = size;
2035 } else {
2036 printf("*** Error writing address "REG"\n", adrs + n);
2037 }
2038 catch_memory_errors = 0;
2039 return n;
2040}
2041
2042static int fault_type;
2043static int fault_except;
2044static char *fault_chars[] = { "--", "**", "##" };
2045
2046static int handle_fault(struct pt_regs *regs)
2047{
2048 fault_except = TRAP(regs);
2049 switch (TRAP(regs)) {
2050 case 0x200:
2051 fault_type = 0;
2052 break;
2053 case 0x300:
2054 case 0x380:
2055 fault_type = 1;
2056 break;
2057 default:
2058 fault_type = 2;
2059 }
2060
2061 longjmp(bus_error_jmp, 1);
2062
2063 return 0;
2064}
2065
2066#define SWAP(a, b, t) ((t) = (a), (a) = (b), (b) = (t))
2067
2068static void
2069byterev(unsigned char *val, int size)
2070{
2071 int t;
2072
2073 switch (size) {
2074 case 2:
2075 SWAP(val[0], val[1], t);
2076 break;
2077 case 4:
2078 SWAP(val[0], val[3], t);
2079 SWAP(val[1], val[2], t);
2080 break;
2081 case 8:
2082 SWAP(val[0], val[7], t);
2083 SWAP(val[1], val[6], t);
2084 SWAP(val[2], val[5], t);
2085 SWAP(val[3], val[4], t);
2086 break;
2087 }
2088}
2089
2090static int brev;
2091static int mnoread;
2092
2093static char *memex_help_string =
2094 "Memory examine command usage:\n"
2095 "m [addr] [flags] examine/change memory\n"
2096 " addr is optional. will start where left off.\n"
2097 " flags may include chars from this set:\n"
2098 " b modify by bytes (default)\n"
2099 " w modify by words (2 byte)\n"
2100 " l modify by longs (4 byte)\n"
2101 " d modify by doubleword (8 byte)\n"
2102 " r toggle reverse byte order mode\n"
2103 " n do not read memory (for i/o spaces)\n"
2104 " . ok to read (default)\n"
2105 "NOTE: flags are saved as defaults\n"
2106 "";
2107
2108static char *memex_subcmd_help_string =
2109 "Memory examine subcommands:\n"
2110 " hexval write this val to current location\n"
2111 " 'string' write chars from string to this location\n"
2112 " ' increment address\n"
2113 " ^ decrement address\n"
2114 " / increment addr by 0x10. //=0x100, ///=0x1000, etc\n"
2115 " \\ decrement addr by 0x10. \\\\=0x100, \\\\\\=0x1000, etc\n"
2116 " ` clear no-read flag\n"
2117 " ; stay at this addr\n"
2118 " v change to byte mode\n"
2119 " w change to word (2 byte) mode\n"
2120 " l change to long (4 byte) mode\n"
2121 " u change to doubleword (8 byte) mode\n"
2122 " m addr change current addr\n"
2123 " n toggle no-read flag\n"
2124 " r toggle byte reverse flag\n"
2125 " < count back up count bytes\n"
2126 " > count skip forward count bytes\n"
2127 " x exit this mode\n"
2128 "";
2129
2130static void
2131memex(void)
2132{
2133 int cmd, inc, i, nslash;
2134 unsigned long n;
2135 unsigned char val[16];
2136
2137 scanhex((void *)&adrs);
2138 cmd = skipbl();
2139 if (cmd == '?') {
2140 printf(memex_help_string);
2141 return;
2142 } else {
2143 termch = cmd;
2144 }
2145 last_cmd = "m\n";
2146 while ((cmd = skipbl()) != '\n') {
2147 switch( cmd ){
2148 case 'b': size = 1; break;
2149 case 'w': size = 2; break;
2150 case 'l': size = 4; break;
2151 case 'd': size = 8; break;
2152 case 'r': brev = !brev; break;
2153 case 'n': mnoread = 1; break;
2154 case '.': mnoread = 0; break;
2155 }
2156 }
2157 if( size <= 0 )
2158 size = 1;
2159 else if( size > 8 )
2160 size = 8;
2161 for(;;){
2162 if (!mnoread)
2163 n = mread(adrs, val, size);
2164 printf(REG"%c", adrs, brev? 'r': ' ');
2165 if (!mnoread) {
2166 if (brev)
2167 byterev(val, size);
2168 putchar(' ');
2169 for (i = 0; i < n; ++i)
2170 printf("%.2x", val[i]);
2171 for (; i < size; ++i)
2172 printf("%s", fault_chars[fault_type]);
2173 }
2174 putchar(' ');
2175 inc = size;
2176 nslash = 0;
2177 for(;;){
2178 if( scanhex(&n) ){
2179 for (i = 0; i < size; ++i)
2180 val[i] = n >> (i * 8);
2181 if (!brev)
2182 byterev(val, size);
2183 mwrite(adrs, val, size);
2184 inc = size;
2185 }
2186 cmd = skipbl();
2187 if (cmd == '\n')
2188 break;
2189 inc = 0;
2190 switch (cmd) {
2191 case '\'':
2192 for(;;){
2193 n = inchar();
2194 if( n == '\\' )
2195 n = bsesc();
2196 else if( n == '\'' )
2197 break;
2198 for (i = 0; i < size; ++i)
2199 val[i] = n >> (i * 8);
2200 if (!brev)
2201 byterev(val, size);
2202 mwrite(adrs, val, size);
2203 adrs += size;
2204 }
2205 adrs -= size;
2206 inc = size;
2207 break;
2208 case ',':
2209 adrs += size;
2210 break;
2211 case '.':
2212 mnoread = 0;
2213 break;
2214 case ';':
2215 break;
2216 case 'x':
2217 case EOF:
2218 scannl();
2219 return;
2220 case 'b':
2221 case 'v':
2222 size = 1;
2223 break;
2224 case 'w':
2225 size = 2;
2226 break;
2227 case 'l':
2228 size = 4;
2229 break;
2230 case 'u':
2231 size = 8;
2232 break;
2233 case '^':
2234 adrs -= size;
2235 break;
2236 case '/':
2237 if (nslash > 0)
2238 adrs -= 1 << nslash;
2239 else
2240 nslash = 0;
2241 nslash += 4;
2242 adrs += 1 << nslash;
2243 break;
2244 case '\\':
2245 if (nslash < 0)
2246 adrs += 1 << -nslash;
2247 else
2248 nslash = 0;
2249 nslash -= 4;
2250 adrs -= 1 << -nslash;
2251 break;
2252 case 'm':
2253 scanhex((void *)&adrs);
2254 break;
2255 case 'n':
2256 mnoread = 1;
2257 break;
2258 case 'r':
2259 brev = !brev;
2260 break;
2261 case '<':
2262 n = size;
2263 scanhex(&n);
2264 adrs -= n;
2265 break;
2266 case '>':
2267 n = size;
2268 scanhex(&n);
2269 adrs += n;
2270 break;
2271 case '?':
2272 printf(memex_subcmd_help_string);
2273 break;
2274 }
2275 }
2276 adrs += inc;
2277 }
2278}
2279
2280static int
2281bsesc(void)
2282{
2283 int c;
2284
2285 c = inchar();
2286 switch( c ){
2287 case 'n': c = '\n'; break;
2288 case 'r': c = '\r'; break;
2289 case 'b': c = '\b'; break;
2290 case 't': c = '\t'; break;
2291 }
2292 return c;
2293}
2294
2295static void xmon_rawdump (unsigned long adrs, long ndump)
2296{
2297 long n, m, r, nr;
2298 unsigned char temp[16];
2299
2300 for (n = ndump; n > 0;) {
2301 r = n < 16? n: 16;
2302 nr = mread(adrs, temp, r);
2303 adrs += nr;
2304 for (m = 0; m < r; ++m) {
2305 if (m < nr)
2306 printf("%.2x", temp[m]);
2307 else
2308 printf("%s", fault_chars[fault_type]);
2309 }
2310 n -= r;
2311 if (nr < r)
2312 break;
2313 }
2314 printf("\n");
2315}
2316
2317static void dump_tracing(void)
2318{
2319 int c;
2320
2321 c = inchar();
2322 if (c == 'c')
2323 ftrace_dump(DUMP_ORIG);
2324 else
2325 ftrace_dump(DUMP_ALL);
2326}
2327
2328#ifdef CONFIG_PPC64
2329static void dump_one_paca(int cpu)
2330{
2331 struct paca_struct *p;
2332#ifdef CONFIG_PPC_BOOK3S_64
2333 int i = 0;
2334#endif
2335
2336 if (setjmp(bus_error_jmp) != 0) {
2337 printf("*** Error dumping paca for cpu 0x%x!\n", cpu);
2338 return;
2339 }
2340
2341 catch_memory_errors = 1;
2342 sync();
2343
2344 p = paca_ptrs[cpu];
2345
2346 printf("paca for cpu 0x%x @ %px:\n", cpu, p);
2347
2348 printf(" %-*s = %s\n", 20, "possible", cpu_possible(cpu) ? "yes" : "no");
2349 printf(" %-*s = %s\n", 20, "present", cpu_present(cpu) ? "yes" : "no");
2350 printf(" %-*s = %s\n", 20, "online", cpu_online(cpu) ? "yes" : "no");
2351
2352#define DUMP(paca, name, format) \
2353 printf(" %-*s = %#-*"format"\t(0x%lx)\n", 20, #name, 18, paca->name, \
2354 offsetof(struct paca_struct, name));
2355
2356 DUMP(p, lock_token, "x");
2357 DUMP(p, paca_index, "x");
2358 DUMP(p, kernel_toc, "lx");
2359 DUMP(p, kernelbase, "lx");
2360 DUMP(p, kernel_msr, "lx");
2361 DUMP(p, emergency_sp, "px");
2362#ifdef CONFIG_PPC_BOOK3S_64
2363 DUMP(p, nmi_emergency_sp, "px");
2364 DUMP(p, mc_emergency_sp, "px");
2365 DUMP(p, in_nmi, "x");
2366 DUMP(p, in_mce, "x");
2367 DUMP(p, hmi_event_available, "x");
2368#endif
2369 DUMP(p, data_offset, "lx");
2370 DUMP(p, hw_cpu_id, "x");
2371 DUMP(p, cpu_start, "x");
2372 DUMP(p, kexec_state, "x");
2373#ifdef CONFIG_PPC_BOOK3S_64
2374 for (i = 0; i < SLB_NUM_BOLTED; i++) {
2375 u64 esid, vsid;
2376
2377 if (!p->slb_shadow_ptr)
2378 continue;
2379
2380 esid = be64_to_cpu(p->slb_shadow_ptr->save_area[i].esid);
2381 vsid = be64_to_cpu(p->slb_shadow_ptr->save_area[i].vsid);
2382
2383 if (esid || vsid) {
2384 printf(" slb_shadow[%d]: = 0x%016lx 0x%016lx\n",
2385 i, esid, vsid);
2386 }
2387 }
2388 DUMP(p, vmalloc_sllp, "x");
2389 DUMP(p, slb_cache_ptr, "x");
2390 for (i = 0; i < SLB_CACHE_ENTRIES; i++)
2391 printf(" slb_cache[%d]: = 0x%016lx\n", i, p->slb_cache[i]);
2392
2393 DUMP(p, rfi_flush_fallback_area, "px");
2394#endif
2395 DUMP(p, dscr_default, "llx");
2396#ifdef CONFIG_PPC_BOOK3E
2397 DUMP(p, pgd, "px");
2398 DUMP(p, kernel_pgd, "px");
2399 DUMP(p, tcd_ptr, "px");
2400 DUMP(p, mc_kstack, "px");
2401 DUMP(p, crit_kstack, "px");
2402 DUMP(p, dbg_kstack, "px");
2403#endif
2404 DUMP(p, __current, "px");
2405 DUMP(p, kstack, "lx");
2406 printf(" kstack_base = 0x%016lx\n", p->kstack & ~(THREAD_SIZE - 1));
2407 DUMP(p, stab_rr, "lx");
2408 DUMP(p, saved_r1, "lx");
2409 DUMP(p, trap_save, "x");
2410 DUMP(p, irq_soft_mask, "x");
2411 DUMP(p, irq_happened, "x");
2412 DUMP(p, io_sync, "x");
2413 DUMP(p, irq_work_pending, "x");
2414 DUMP(p, nap_state_lost, "x");
2415 DUMP(p, sprg_vdso, "llx");
2416
2417#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
2418 DUMP(p, tm_scratch, "llx");
2419#endif
2420
2421#ifdef CONFIG_PPC_POWERNV
2422 DUMP(p, core_idle_state_ptr, "px");
2423 DUMP(p, thread_idle_state, "x");
2424 DUMP(p, thread_mask, "x");
2425 DUMP(p, subcore_sibling_mask, "x");
2426#endif
2427
2428 DUMP(p, accounting.utime, "llx");
2429 DUMP(p, accounting.stime, "llx");
2430 DUMP(p, accounting.utime_scaled, "llx");
2431 DUMP(p, accounting.starttime, "llx");
2432 DUMP(p, accounting.starttime_user, "llx");
2433 DUMP(p, accounting.startspurr, "llx");
2434 DUMP(p, accounting.utime_sspurr, "llx");
2435 DUMP(p, accounting.steal_time, "llx");
2436#undef DUMP
2437
2438 catch_memory_errors = 0;
2439 sync();
2440}
2441
2442static void dump_all_pacas(void)
2443{
2444 int cpu;
2445
2446 if (num_possible_cpus() == 0) {
2447 printf("No possible cpus, use 'dp #' to dump individual cpus\n");
2448 return;
2449 }
2450
2451 for_each_possible_cpu(cpu)
2452 dump_one_paca(cpu);
2453}
2454
2455static void dump_pacas(void)
2456{
2457 unsigned long num;
2458 int c;
2459
2460 c = inchar();
2461 if (c == 'a') {
2462 dump_all_pacas();
2463 return;
2464 }
2465
2466 termch = c;
2467
2468 if (scanhex(&num))
2469 dump_one_paca(num);
2470 else
2471 dump_one_paca(xmon_owner);
2472}
2473#endif
2474
2475#ifdef CONFIG_PPC_POWERNV
2476static void dump_one_xive(int cpu)
2477{
2478 unsigned int hwid = get_hard_smp_processor_id(cpu);
2479
2480 opal_xive_dump(XIVE_DUMP_TM_HYP, hwid);
2481 opal_xive_dump(XIVE_DUMP_TM_POOL, hwid);
2482 opal_xive_dump(XIVE_DUMP_TM_OS, hwid);
2483 opal_xive_dump(XIVE_DUMP_TM_USER, hwid);
2484 opal_xive_dump(XIVE_DUMP_VP, hwid);
2485 opal_xive_dump(XIVE_DUMP_EMU_STATE, hwid);
2486
2487 if (setjmp(bus_error_jmp) != 0) {
2488 catch_memory_errors = 0;
2489 printf("*** Error dumping xive on cpu %d\n", cpu);
2490 return;
2491 }
2492
2493 catch_memory_errors = 1;
2494 sync();
2495 xmon_xive_do_dump(cpu);
2496 sync();
2497 __delay(200);
2498 catch_memory_errors = 0;
2499}
2500
2501static void dump_all_xives(void)
2502{
2503 int cpu;
2504
2505 if (num_possible_cpus() == 0) {
2506 printf("No possible cpus, use 'dx #' to dump individual cpus\n");
2507 return;
2508 }
2509
2510 for_each_possible_cpu(cpu)
2511 dump_one_xive(cpu);
2512}
2513
2514static void dump_one_xive_irq(u32 num)
2515{
2516 s64 rc;
2517 __be64 vp;
2518 u8 prio;
2519 __be32 lirq;
2520
2521 rc = opal_xive_get_irq_config(num, &vp, &prio, &lirq);
2522 xmon_printf("IRQ 0x%x config: vp=0x%llx prio=%d lirq=0x%x (rc=%lld)\n",
2523 num, be64_to_cpu(vp), prio, be32_to_cpu(lirq), rc);
2524}
2525
2526static void dump_xives(void)
2527{
2528 unsigned long num;
2529 int c;
2530
2531 if (!xive_enabled()) {
2532 printf("Xive disabled on this system\n");
2533 return;
2534 }
2535
2536 c = inchar();
2537 if (c == 'a') {
2538 dump_all_xives();
2539 return;
2540 } else if (c == 'i') {
2541 if (scanhex(&num))
2542 dump_one_xive_irq(num);
2543 return;
2544 }
2545
2546 termch = c;
2547
2548 if (scanhex(&num))
2549 dump_one_xive(num);
2550 else
2551 dump_one_xive(xmon_owner);
2552}
2553#endif
2554
2555static void dump_by_size(unsigned long addr, long count, int size)
2556{
2557 unsigned char temp[16];
2558 int i, j;
2559 u64 val;
2560
2561 count = ALIGN(count, 16);
2562
2563 for (i = 0; i < count; i += 16, addr += 16) {
2564 printf(REG, addr);
2565
2566 if (mread(addr, temp, 16) != 16) {
2567 printf("\nFaulted reading %d bytes from 0x"REG"\n", 16, addr);
2568 return;
2569 }
2570
2571 for (j = 0; j < 16; j += size) {
2572 putchar(' ');
2573 switch (size) {
2574 case 1: val = temp[j]; break;
2575 case 2: val = *(u16 *)&temp[j]; break;
2576 case 4: val = *(u32 *)&temp[j]; break;
2577 case 8: val = *(u64 *)&temp[j]; break;
2578 default: val = 0;
2579 }
2580
2581 printf("%0*lx", size * 2, val);
2582 }
2583 printf("\n");
2584 }
2585}
2586
2587static void
2588dump(void)
2589{
2590 static char last[] = { "d?\n" };
2591 int c;
2592
2593 c = inchar();
2594
2595#ifdef CONFIG_PPC64
2596 if (c == 'p') {
2597 xmon_start_pagination();
2598 dump_pacas();
2599 xmon_end_pagination();
2600 return;
2601 }
2602#endif
2603#ifdef CONFIG_PPC_POWERNV
2604 if (c == 'x') {
2605 xmon_start_pagination();
2606 dump_xives();
2607 xmon_end_pagination();
2608 return;
2609 }
2610#endif
2611
2612 if (c == 't') {
2613 dump_tracing();
2614 return;
2615 }
2616
2617 if (c == '\n')
2618 termch = c;
2619
2620 scanhex((void *)&adrs);
2621 if (termch != '\n')
2622 termch = 0;
2623 if (c == 'i') {
2624 scanhex(&nidump);
2625 if (nidump == 0)
2626 nidump = 16;
2627 else if (nidump > MAX_DUMP)
2628 nidump = MAX_DUMP;
2629 adrs += ppc_inst_dump(adrs, nidump, 1);
2630 last_cmd = "di\n";
2631 } else if (c == 'l') {
2632 dump_log_buf();
2633 } else if (c == 'o') {
2634 dump_opal_msglog();
2635 } else if (c == 'v') {
2636
2637 show_pte(adrs);
2638 } else if (c == 'r') {
2639 scanhex(&ndump);
2640 if (ndump == 0)
2641 ndump = 64;
2642 xmon_rawdump(adrs, ndump);
2643 adrs += ndump;
2644 last_cmd = "dr\n";
2645 } else {
2646 scanhex(&ndump);
2647 if (ndump == 0)
2648 ndump = 64;
2649 else if (ndump > MAX_DUMP)
2650 ndump = MAX_DUMP;
2651
2652 switch (c) {
2653 case '8':
2654 case '4':
2655 case '2':
2656 case '1':
2657 ndump = ALIGN(ndump, 16);
2658 dump_by_size(adrs, ndump, c - '0');
2659 last[1] = c;
2660 last_cmd = last;
2661 break;
2662 default:
2663 prdump(adrs, ndump);
2664 last_cmd = "d\n";
2665 }
2666
2667 adrs += ndump;
2668 }
2669}
2670
2671static void
2672prdump(unsigned long adrs, long ndump)
2673{
2674 long n, m, c, r, nr;
2675 unsigned char temp[16];
2676
2677 for (n = ndump; n > 0;) {
2678 printf(REG, adrs);
2679 putchar(' ');
2680 r = n < 16? n: 16;
2681 nr = mread(adrs, temp, r);
2682 adrs += nr;
2683 for (m = 0; m < r; ++m) {
2684 if ((m & (sizeof(long) - 1)) == 0 && m > 0)
2685 putchar(' ');
2686 if (m < nr)
2687 printf("%.2x", temp[m]);
2688 else
2689 printf("%s", fault_chars[fault_type]);
2690 }
2691 for (; m < 16; ++m) {
2692 if ((m & (sizeof(long) - 1)) == 0)
2693 putchar(' ');
2694 printf(" ");
2695 }
2696 printf(" |");
2697 for (m = 0; m < r; ++m) {
2698 if (m < nr) {
2699 c = temp[m];
2700 putchar(' ' <= c && c <= '~'? c: '.');
2701 } else
2702 putchar(' ');
2703 }
2704 n -= r;
2705 for (; m < 16; ++m)
2706 putchar(' ');
2707 printf("|\n");
2708 if (nr < r)
2709 break;
2710 }
2711}
2712
2713typedef int (*instruction_dump_func)(unsigned long inst, unsigned long addr);
2714
2715static int
2716generic_inst_dump(unsigned long adr, long count, int praddr,
2717 instruction_dump_func dump_func)
2718{
2719 int nr, dotted;
2720 unsigned long first_adr;
2721 unsigned long inst, last_inst = 0;
2722 unsigned char val[4];
2723
2724 dotted = 0;
2725 for (first_adr = adr; count > 0; --count, adr += 4) {
2726 nr = mread(adr, val, 4);
2727 if (nr == 0) {
2728 if (praddr) {
2729 const char *x = fault_chars[fault_type];
2730 printf(REG" %s%s%s%s\n", adr, x, x, x, x);
2731 }
2732 break;
2733 }
2734 inst = GETWORD(val);
2735 if (adr > first_adr && inst == last_inst) {
2736 if (!dotted) {
2737 printf(" ...\n");
2738 dotted = 1;
2739 }
2740 continue;
2741 }
2742 dotted = 0;
2743 last_inst = inst;
2744 if (praddr)
2745 printf(REG" %.8x", adr, inst);
2746 printf("\t");
2747 dump_func(inst, adr);
2748 printf("\n");
2749 }
2750 return adr - first_adr;
2751}
2752
2753static int
2754ppc_inst_dump(unsigned long adr, long count, int praddr)
2755{
2756 return generic_inst_dump(adr, count, praddr, print_insn_powerpc);
2757}
2758
2759void
2760print_address(unsigned long addr)
2761{
2762 xmon_print_symbol(addr, "\t# ", "");
2763}
2764
2765void
2766dump_log_buf(void)
2767{
2768 struct kmsg_dumper dumper = { .active = 1 };
2769 unsigned char buf[128];
2770 size_t len;
2771
2772 if (setjmp(bus_error_jmp) != 0) {
2773 printf("Error dumping printk buffer!\n");
2774 return;
2775 }
2776
2777 catch_memory_errors = 1;
2778 sync();
2779
2780 kmsg_dump_rewind_nolock(&dumper);
2781 xmon_start_pagination();
2782 while (kmsg_dump_get_line_nolock(&dumper, false, buf, sizeof(buf), &len)) {
2783 buf[len] = '\0';
2784 printf("%s", buf);
2785 }
2786 xmon_end_pagination();
2787
2788 sync();
2789
2790 __delay(200);
2791 catch_memory_errors = 0;
2792}
2793
2794#ifdef CONFIG_PPC_POWERNV
2795static void dump_opal_msglog(void)
2796{
2797 unsigned char buf[128];
2798 ssize_t res;
2799 loff_t pos = 0;
2800
2801 if (!firmware_has_feature(FW_FEATURE_OPAL)) {
2802 printf("Machine is not running OPAL firmware.\n");
2803 return;
2804 }
2805
2806 if (setjmp(bus_error_jmp) != 0) {
2807 printf("Error dumping OPAL msglog!\n");
2808 return;
2809 }
2810
2811 catch_memory_errors = 1;
2812 sync();
2813
2814 xmon_start_pagination();
2815 while ((res = opal_msglog_copy(buf, pos, sizeof(buf) - 1))) {
2816 if (res < 0) {
2817 printf("Error dumping OPAL msglog! Error: %zd\n", res);
2818 break;
2819 }
2820 buf[res] = '\0';
2821 printf("%s", buf);
2822 pos += res;
2823 }
2824 xmon_end_pagination();
2825
2826 sync();
2827
2828 __delay(200);
2829 catch_memory_errors = 0;
2830}
2831#endif
2832
2833
2834
2835
2836static unsigned long mdest;
2837static unsigned long msrc;
2838static unsigned long mval;
2839static unsigned long mcount;
2840static unsigned long mdiffs;
2841
2842static void
2843memops(int cmd)
2844{
2845 scanhex((void *)&mdest);
2846 if( termch != '\n' )
2847 termch = 0;
2848 scanhex((void *)(cmd == 's'? &mval: &msrc));
2849 if( termch != '\n' )
2850 termch = 0;
2851 scanhex((void *)&mcount);
2852 switch( cmd ){
2853 case 'm':
2854 memmove((void *)mdest, (void *)msrc, mcount);
2855 break;
2856 case 's':
2857 memset((void *)mdest, mval, mcount);
2858 break;
2859 case 'd':
2860 if( termch != '\n' )
2861 termch = 0;
2862 scanhex((void *)&mdiffs);
2863 memdiffs((unsigned char *)mdest, (unsigned char *)msrc, mcount, mdiffs);
2864 break;
2865 }
2866}
2867
2868static void
2869memdiffs(unsigned char *p1, unsigned char *p2, unsigned nb, unsigned maxpr)
2870{
2871 unsigned n, prt;
2872
2873 prt = 0;
2874 for( n = nb; n > 0; --n )
2875 if( *p1++ != *p2++ )
2876 if( ++prt <= maxpr )
2877 printf("%.16x %.2x # %.16x %.2x\n", p1 - 1,
2878 p1[-1], p2 - 1, p2[-1]);
2879 if( prt > maxpr )
2880 printf("Total of %d differences\n", prt);
2881}
2882
2883static unsigned mend;
2884static unsigned mask;
2885
2886static void
2887memlocate(void)
2888{
2889 unsigned a, n;
2890 unsigned char val[4];
2891
2892 last_cmd = "ml";
2893 scanhex((void *)&mdest);
2894 if (termch != '\n') {
2895 termch = 0;
2896 scanhex((void *)&mend);
2897 if (termch != '\n') {
2898 termch = 0;
2899 scanhex((void *)&mval);
2900 mask = ~0;
2901 if (termch != '\n') termch = 0;
2902 scanhex((void *)&mask);
2903 }
2904 }
2905 n = 0;
2906 for (a = mdest; a < mend; a += 4) {
2907 if (mread(a, val, 4) == 4
2908 && ((GETWORD(val) ^ mval) & mask) == 0) {
2909 printf("%.16x: %.16x\n", a, GETWORD(val));
2910 if (++n >= 10)
2911 break;
2912 }
2913 }
2914}
2915
2916static unsigned long mskip = 0x1000;
2917static unsigned long mlim = 0xffffffff;
2918
2919static void
2920memzcan(void)
2921{
2922 unsigned char v;
2923 unsigned a;
2924 int ok, ook;
2925
2926 scanhex(&mdest);
2927 if (termch != '\n') termch = 0;
2928 scanhex(&mskip);
2929 if (termch != '\n') termch = 0;
2930 scanhex(&mlim);
2931 ook = 0;
2932 for (a = mdest; a < mlim; a += mskip) {
2933 ok = mread(a, &v, 1);
2934 if (ok && !ook) {
2935 printf("%.8x .. ", a);
2936 } else if (!ok && ook)
2937 printf("%.8x\n", a - mskip);
2938 ook = ok;
2939 if (a + mskip < a)
2940 break;
2941 }
2942 if (ook)
2943 printf("%.8x\n", a - mskip);
2944}
2945
2946static void show_task(struct task_struct *tsk)
2947{
2948 char state;
2949
2950
2951
2952
2953
2954
2955 state = (tsk->state == 0) ? 'R' :
2956 (tsk->state < 0) ? 'U' :
2957 (tsk->state & TASK_UNINTERRUPTIBLE) ? 'D' :
2958 (tsk->state & TASK_STOPPED) ? 'T' :
2959 (tsk->state & TASK_TRACED) ? 'C' :
2960 (tsk->exit_state & EXIT_ZOMBIE) ? 'Z' :
2961 (tsk->exit_state & EXIT_DEAD) ? 'E' :
2962 (tsk->state & TASK_INTERRUPTIBLE) ? 'S' : '?';
2963
2964 printf("%px %016lx %6d %6d %c %2d %s\n", tsk,
2965 tsk->thread.ksp,
2966 tsk->pid, tsk->parent->pid,
2967 state, task_thread_info(tsk)->cpu,
2968 tsk->comm);
2969}
2970
2971#ifdef CONFIG_PPC_BOOK3S_64
2972void format_pte(void *ptep, unsigned long pte)
2973{
2974 printf("ptep @ 0x%016lx = 0x%016lx\n", (unsigned long)ptep, pte);
2975 printf("Maps physical address = 0x%016lx\n", pte & PTE_RPN_MASK);
2976
2977 printf("Flags = %s%s%s%s%s\n",
2978 (pte & _PAGE_ACCESSED) ? "Accessed " : "",
2979 (pte & _PAGE_DIRTY) ? "Dirty " : "",
2980 (pte & _PAGE_READ) ? "Read " : "",
2981 (pte & _PAGE_WRITE) ? "Write " : "",
2982 (pte & _PAGE_EXEC) ? "Exec " : "");
2983}
2984
2985static void show_pte(unsigned long addr)
2986{
2987 unsigned long tskv = 0;
2988 struct task_struct *tsk = NULL;
2989 struct mm_struct *mm;
2990 pgd_t *pgdp, *pgdir;
2991 pud_t *pudp;
2992 pmd_t *pmdp;
2993 pte_t *ptep;
2994
2995 if (!scanhex(&tskv))
2996 mm = &init_mm;
2997 else
2998 tsk = (struct task_struct *)tskv;
2999
3000 if (tsk == NULL)
3001 mm = &init_mm;
3002 else
3003 mm = tsk->active_mm;
3004
3005 if (setjmp(bus_error_jmp) != 0) {
3006 catch_memory_errors = 0;
3007 printf("*** Error dumping pte for task %px\n", tsk);
3008 return;
3009 }
3010
3011 catch_memory_errors = 1;
3012 sync();
3013
3014 if (mm == &init_mm) {
3015 pgdp = pgd_offset_k(addr);
3016 pgdir = pgd_offset_k(0);
3017 } else {
3018 pgdp = pgd_offset(mm, addr);
3019 pgdir = pgd_offset(mm, 0);
3020 }
3021
3022 if (pgd_none(*pgdp)) {
3023 printf("no linux page table for address\n");
3024 return;
3025 }
3026
3027 printf("pgd @ 0x%016lx\n", pgdir);
3028
3029 if (pgd_huge(*pgdp)) {
3030 format_pte(pgdp, pgd_val(*pgdp));
3031 return;
3032 }
3033 printf("pgdp @ 0x%016lx = 0x%016lx\n", pgdp, pgd_val(*pgdp));
3034
3035 pudp = pud_offset(pgdp, addr);
3036
3037 if (pud_none(*pudp)) {
3038 printf("No valid PUD\n");
3039 return;
3040 }
3041
3042 if (pud_huge(*pudp)) {
3043 format_pte(pudp, pud_val(*pudp));
3044 return;
3045 }
3046
3047 printf("pudp @ 0x%016lx = 0x%016lx\n", pudp, pud_val(*pudp));
3048
3049 pmdp = pmd_offset(pudp, addr);
3050
3051 if (pmd_none(*pmdp)) {
3052 printf("No valid PMD\n");
3053 return;
3054 }
3055
3056 if (pmd_huge(*pmdp)) {
3057 format_pte(pmdp, pmd_val(*pmdp));
3058 return;
3059 }
3060 printf("pmdp @ 0x%016lx = 0x%016lx\n", pmdp, pmd_val(*pmdp));
3061
3062 ptep = pte_offset_map(pmdp, addr);
3063 if (pte_none(*ptep)) {
3064 printf("no valid PTE\n");
3065 return;
3066 }
3067
3068 format_pte(ptep, pte_val(*ptep));
3069
3070 sync();
3071 __delay(200);
3072 catch_memory_errors = 0;
3073}
3074#else
3075static void show_pte(unsigned long addr)
3076{
3077 printf("show_pte not yet implemented\n");
3078}
3079#endif
3080
3081static void show_tasks(void)
3082{
3083 unsigned long tskv;
3084 struct task_struct *tsk = NULL;
3085
3086 printf(" task_struct ->thread.ksp PID PPID S P CMD\n");
3087
3088 if (scanhex(&tskv))
3089 tsk = (struct task_struct *)tskv;
3090
3091 if (setjmp(bus_error_jmp) != 0) {
3092 catch_memory_errors = 0;
3093 printf("*** Error dumping task %px\n", tsk);
3094 return;
3095 }
3096
3097 catch_memory_errors = 1;
3098 sync();
3099
3100 if (tsk)
3101 show_task(tsk);
3102 else
3103 for_each_process(tsk)
3104 show_task(tsk);
3105
3106 sync();
3107 __delay(200);
3108 catch_memory_errors = 0;
3109}
3110
3111static void proccall(void)
3112{
3113 unsigned long args[8];
3114 unsigned long ret;
3115 int i;
3116 typedef unsigned long (*callfunc_t)(unsigned long, unsigned long,
3117 unsigned long, unsigned long, unsigned long,
3118 unsigned long, unsigned long, unsigned long);
3119 callfunc_t func;
3120
3121 if (!scanhex(&adrs))
3122 return;
3123 if (termch != '\n')
3124 termch = 0;
3125 for (i = 0; i < 8; ++i)
3126 args[i] = 0;
3127 for (i = 0; i < 8; ++i) {
3128 if (!scanhex(&args[i]) || termch == '\n')
3129 break;
3130 termch = 0;
3131 }
3132 func = (callfunc_t) adrs;
3133 ret = 0;
3134 if (setjmp(bus_error_jmp) == 0) {
3135 catch_memory_errors = 1;
3136 sync();
3137 ret = func(args[0], args[1], args[2], args[3],
3138 args[4], args[5], args[6], args[7]);
3139 sync();
3140 printf("return value is 0x%lx\n", ret);
3141 } else {
3142 printf("*** %x exception occurred\n", fault_except);
3143 }
3144 catch_memory_errors = 0;
3145}
3146
3147
3148int
3149skipbl(void)
3150{
3151 int c;
3152
3153 if( termch != 0 ){
3154 c = termch;
3155 termch = 0;
3156 } else
3157 c = inchar();
3158 while( c == ' ' || c == '\t' )
3159 c = inchar();
3160 return c;
3161}
3162
3163#define N_PTREGS 44
3164static char *regnames[N_PTREGS] = {
3165 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
3166 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
3167 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
3168 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
3169 "pc", "msr", "or3", "ctr", "lr", "xer", "ccr",
3170#ifdef CONFIG_PPC64
3171 "softe",
3172#else
3173 "mq",
3174#endif
3175 "trap", "dar", "dsisr", "res"
3176};
3177
3178int
3179scanhex(unsigned long *vp)
3180{
3181 int c, d;
3182 unsigned long v;
3183
3184 c = skipbl();
3185 if (c == '%') {
3186
3187 char regname[8];
3188 int i;
3189
3190 for (i = 0; i < sizeof(regname) - 1; ++i) {
3191 c = inchar();
3192 if (!isalnum(c)) {
3193 termch = c;
3194 break;
3195 }
3196 regname[i] = c;
3197 }
3198 regname[i] = 0;
3199 for (i = 0; i < N_PTREGS; ++i) {
3200 if (strcmp(regnames[i], regname) == 0) {
3201 if (xmon_regs == NULL) {
3202 printf("regs not available\n");
3203 return 0;
3204 }
3205 *vp = ((unsigned long *)xmon_regs)[i];
3206 return 1;
3207 }
3208 }
3209 printf("invalid register name '%%%s'\n", regname);
3210 return 0;
3211 }
3212
3213
3214
3215 if (c == '0') {
3216 c = inchar();
3217 if (c == 'x') {
3218 c = inchar();
3219 } else {
3220 d = hexdigit(c);
3221 if (d == EOF) {
3222 termch = c;
3223 *vp = 0;
3224 return 1;
3225 }
3226 }
3227 } else if (c == '$') {
3228 int i;
3229 for (i=0; i<63; i++) {
3230 c = inchar();
3231 if (isspace(c) || c == '\0') {
3232 termch = c;
3233 break;
3234 }
3235 tmpstr[i] = c;
3236 }
3237 tmpstr[i++] = 0;
3238 *vp = 0;
3239 if (setjmp(bus_error_jmp) == 0) {
3240 catch_memory_errors = 1;
3241 sync();
3242 *vp = kallsyms_lookup_name(tmpstr);
3243 sync();
3244 }
3245 catch_memory_errors = 0;
3246 if (!(*vp)) {
3247 printf("unknown symbol '%s'\n", tmpstr);
3248 return 0;
3249 }
3250 return 1;
3251 }
3252
3253 d = hexdigit(c);
3254 if (d == EOF) {
3255 termch = c;
3256 return 0;
3257 }
3258 v = 0;
3259 do {
3260 v = (v << 4) + d;
3261 c = inchar();
3262 d = hexdigit(c);
3263 } while (d != EOF);
3264 termch = c;
3265 *vp = v;
3266 return 1;
3267}
3268
3269static void
3270scannl(void)
3271{
3272 int c;
3273
3274 c = termch;
3275 termch = 0;
3276 while( c != '\n' )
3277 c = inchar();
3278}
3279
3280static int hexdigit(int c)
3281{
3282 if( '0' <= c && c <= '9' )
3283 return c - '0';
3284 if( 'A' <= c && c <= 'F' )
3285 return c - ('A' - 10);
3286 if( 'a' <= c && c <= 'f' )
3287 return c - ('a' - 10);
3288 return EOF;
3289}
3290
3291void
3292getstring(char *s, int size)
3293{
3294 int c;
3295
3296 c = skipbl();
3297 do {
3298 if( size > 1 ){
3299 *s++ = c;
3300 --size;
3301 }
3302 c = inchar();
3303 } while( c != ' ' && c != '\t' && c != '\n' );
3304 termch = c;
3305 *s = 0;
3306}
3307
3308static char line[256];
3309static char *lineptr;
3310
3311static void
3312flush_input(void)
3313{
3314 lineptr = NULL;
3315}
3316
3317static int
3318inchar(void)
3319{
3320 if (lineptr == NULL || *lineptr == 0) {
3321 if (xmon_gets(line, sizeof(line)) == NULL) {
3322 lineptr = NULL;
3323 return EOF;
3324 }
3325 lineptr = line;
3326 }
3327 return *lineptr++;
3328}
3329
3330static void
3331take_input(char *str)
3332{
3333 lineptr = str;
3334}
3335
3336
3337static void
3338symbol_lookup(void)
3339{
3340 int type = inchar();
3341 unsigned long addr;
3342 static char tmp[64];
3343
3344 switch (type) {
3345 case 'a':
3346 if (scanhex(&addr))
3347 xmon_print_symbol(addr, ": ", "\n");
3348 termch = 0;
3349 break;
3350 case 's':
3351 getstring(tmp, 64);
3352 if (setjmp(bus_error_jmp) == 0) {
3353 catch_memory_errors = 1;
3354 sync();
3355 addr = kallsyms_lookup_name(tmp);
3356 if (addr)
3357 printf("%s: %lx\n", tmp, addr);
3358 else
3359 printf("Symbol '%s' not found.\n", tmp);
3360 sync();
3361 }
3362 catch_memory_errors = 0;
3363 termch = 0;
3364 break;
3365 }
3366}
3367
3368
3369
3370static void xmon_print_symbol(unsigned long address, const char *mid,
3371 const char *after)
3372{
3373 char *modname;
3374 const char *name = NULL;
3375 unsigned long offset, size;
3376
3377 printf(REG, address);
3378 if (setjmp(bus_error_jmp) == 0) {
3379 catch_memory_errors = 1;
3380 sync();
3381 name = kallsyms_lookup(address, &size, &offset, &modname,
3382 tmpstr);
3383 sync();
3384
3385 __delay(200);
3386 }
3387
3388 catch_memory_errors = 0;
3389
3390 if (name) {
3391 printf("%s%s+%#lx/%#lx", mid, name, offset, size);
3392 if (modname)
3393 printf(" [%s]", modname);
3394 }
3395 printf("%s", after);
3396}
3397
3398#ifdef CONFIG_PPC_BOOK3S_64
3399void dump_segments(void)
3400{
3401 int i;
3402 unsigned long esid,vsid;
3403 unsigned long llp;
3404
3405 printf("SLB contents of cpu 0x%x\n", smp_processor_id());
3406
3407 for (i = 0; i < mmu_slb_size; i++) {
3408 asm volatile("slbmfee %0,%1" : "=r" (esid) : "r" (i));
3409 asm volatile("slbmfev %0,%1" : "=r" (vsid) : "r" (i));
3410
3411 if (!esid && !vsid)
3412 continue;
3413
3414 printf("%02d %016lx %016lx", i, esid, vsid);
3415
3416 if (!(esid & SLB_ESID_V)) {
3417 printf("\n");
3418 continue;
3419 }
3420
3421 llp = vsid & SLB_VSID_LLP;
3422 if (vsid & SLB_VSID_B_1T) {
3423 printf(" 1T ESID=%9lx VSID=%13lx LLP:%3lx \n",
3424 GET_ESID_1T(esid),
3425 (vsid & ~SLB_VSID_B) >> SLB_VSID_SHIFT_1T,
3426 llp);
3427 } else {
3428 printf(" 256M ESID=%9lx VSID=%13lx LLP:%3lx \n",
3429 GET_ESID(esid),
3430 (vsid & ~SLB_VSID_B) >> SLB_VSID_SHIFT,
3431 llp);
3432 }
3433 }
3434}
3435#endif
3436
3437#ifdef CONFIG_PPC_STD_MMU_32
3438void dump_segments(void)
3439{
3440 int i;
3441
3442 printf("sr0-15 =");
3443 for (i = 0; i < 16; ++i)
3444 printf(" %x", mfsrin(i));
3445 printf("\n");
3446}
3447#endif
3448
3449#ifdef CONFIG_44x
3450static void dump_tlb_44x(void)
3451{
3452 int i;
3453
3454 for (i = 0; i < PPC44x_TLB_SIZE; i++) {
3455 unsigned long w0,w1,w2;
3456 asm volatile("tlbre %0,%1,0" : "=r" (w0) : "r" (i));
3457 asm volatile("tlbre %0,%1,1" : "=r" (w1) : "r" (i));
3458 asm volatile("tlbre %0,%1,2" : "=r" (w2) : "r" (i));
3459 printf("[%02x] %08x %08x %08x ", i, w0, w1, w2);
3460 if (w0 & PPC44x_TLB_VALID) {
3461 printf("V %08x -> %01x%08x %c%c%c%c%c",
3462 w0 & PPC44x_TLB_EPN_MASK,
3463 w1 & PPC44x_TLB_ERPN_MASK,
3464 w1 & PPC44x_TLB_RPN_MASK,
3465 (w2 & PPC44x_TLB_W) ? 'W' : 'w',
3466 (w2 & PPC44x_TLB_I) ? 'I' : 'i',
3467 (w2 & PPC44x_TLB_M) ? 'M' : 'm',
3468 (w2 & PPC44x_TLB_G) ? 'G' : 'g',
3469 (w2 & PPC44x_TLB_E) ? 'E' : 'e');
3470 }
3471 printf("\n");
3472 }
3473}
3474#endif
3475
3476#ifdef CONFIG_PPC_BOOK3E
3477static void dump_tlb_book3e(void)
3478{
3479 u32 mmucfg, pidmask, lpidmask;
3480 u64 ramask;
3481 int i, tlb, ntlbs, pidsz, lpidsz, rasz, lrat = 0;
3482 int mmu_version;
3483 static const char *pgsz_names[] = {
3484 " 1K",
3485 " 2K",
3486 " 4K",
3487 " 8K",
3488 " 16K",
3489 " 32K",
3490 " 64K",
3491 "128K",
3492 "256K",
3493 "512K",
3494 " 1M",
3495 " 2M",
3496 " 4M",
3497 " 8M",
3498 " 16M",
3499 " 32M",
3500 " 64M",
3501 "128M",
3502 "256M",
3503 "512M",
3504 " 1G",
3505 " 2G",
3506 " 4G",
3507 " 8G",
3508 " 16G",
3509 " 32G",
3510 " 64G",
3511 "128G",
3512 "256G",
3513 "512G",
3514 " 1T",
3515 " 2T",
3516 };
3517
3518
3519 mmucfg = mfspr(SPRN_MMUCFG);
3520 mmu_version = (mmucfg & 3) + 1;
3521 ntlbs = ((mmucfg >> 2) & 3) + 1;
3522 pidsz = ((mmucfg >> 6) & 0x1f) + 1;
3523 lpidsz = (mmucfg >> 24) & 0xf;
3524 rasz = (mmucfg >> 16) & 0x7f;
3525 if ((mmu_version > 1) && (mmucfg & 0x10000))
3526 lrat = 1;
3527 printf("Book3E MMU MAV=%d.0,%d TLBs,%d-bit PID,%d-bit LPID,%d-bit RA\n",
3528 mmu_version, ntlbs, pidsz, lpidsz, rasz);
3529 pidmask = (1ul << pidsz) - 1;
3530 lpidmask = (1ul << lpidsz) - 1;
3531 ramask = (1ull << rasz) - 1;
3532
3533 for (tlb = 0; tlb < ntlbs; tlb++) {
3534 u32 tlbcfg;
3535 int nent, assoc, new_cc = 1;
3536 printf("TLB %d:\n------\n", tlb);
3537 switch(tlb) {
3538 case 0:
3539 tlbcfg = mfspr(SPRN_TLB0CFG);
3540 break;
3541 case 1:
3542 tlbcfg = mfspr(SPRN_TLB1CFG);
3543 break;
3544 case 2:
3545 tlbcfg = mfspr(SPRN_TLB2CFG);
3546 break;
3547 case 3:
3548 tlbcfg = mfspr(SPRN_TLB3CFG);
3549 break;
3550 default:
3551 printf("Unsupported TLB number !\n");
3552 continue;
3553 }
3554 nent = tlbcfg & 0xfff;
3555 assoc = (tlbcfg >> 24) & 0xff;
3556 for (i = 0; i < nent; i++) {
3557 u32 mas0 = MAS0_TLBSEL(tlb);
3558 u32 mas1 = MAS1_TSIZE(BOOK3E_PAGESZ_4K);
3559 u64 mas2 = 0;
3560 u64 mas7_mas3;
3561 int esel = i, cc = i;
3562
3563 if (assoc != 0) {
3564 cc = i / assoc;
3565 esel = i % assoc;
3566 mas2 = cc * 0x1000;
3567 }
3568
3569 mas0 |= MAS0_ESEL(esel);
3570 mtspr(SPRN_MAS0, mas0);
3571 mtspr(SPRN_MAS1, mas1);
3572 mtspr(SPRN_MAS2, mas2);
3573 asm volatile("tlbre 0,0,0" : : : "memory");
3574 mas1 = mfspr(SPRN_MAS1);
3575 mas2 = mfspr(SPRN_MAS2);
3576 mas7_mas3 = mfspr(SPRN_MAS7_MAS3);
3577 if (assoc && (i % assoc) == 0)
3578 new_cc = 1;
3579 if (!(mas1 & MAS1_VALID))
3580 continue;
3581 if (assoc == 0)
3582 printf("%04x- ", i);
3583 else if (new_cc)
3584 printf("%04x-%c", cc, 'A' + esel);
3585 else
3586 printf(" |%c", 'A' + esel);
3587 new_cc = 0;
3588 printf(" %016llx %04x %s %c%c AS%c",
3589 mas2 & ~0x3ffull,
3590 (mas1 >> 16) & 0x3fff,
3591 pgsz_names[(mas1 >> 7) & 0x1f],
3592 mas1 & MAS1_IND ? 'I' : ' ',
3593 mas1 & MAS1_IPROT ? 'P' : ' ',
3594 mas1 & MAS1_TS ? '1' : '0');
3595 printf(" %c%c%c%c%c%c%c",
3596 mas2 & MAS2_X0 ? 'a' : ' ',
3597 mas2 & MAS2_X1 ? 'v' : ' ',
3598 mas2 & MAS2_W ? 'w' : ' ',
3599 mas2 & MAS2_I ? 'i' : ' ',
3600 mas2 & MAS2_M ? 'm' : ' ',
3601 mas2 & MAS2_G ? 'g' : ' ',
3602 mas2 & MAS2_E ? 'e' : ' ');
3603 printf(" %016llx", mas7_mas3 & ramask & ~0x7ffull);
3604 if (mas1 & MAS1_IND)
3605 printf(" %s\n",
3606 pgsz_names[(mas7_mas3 >> 1) & 0x1f]);
3607 else
3608 printf(" U%c%c%c S%c%c%c\n",
3609 mas7_mas3 & MAS3_UX ? 'x' : ' ',
3610 mas7_mas3 & MAS3_UW ? 'w' : ' ',
3611 mas7_mas3 & MAS3_UR ? 'r' : ' ',
3612 mas7_mas3 & MAS3_SX ? 'x' : ' ',
3613 mas7_mas3 & MAS3_SW ? 'w' : ' ',
3614 mas7_mas3 & MAS3_SR ? 'r' : ' ');
3615 }
3616 }
3617}
3618#endif
3619
3620static void xmon_init(int enable)
3621{
3622 if (enable) {
3623 __debugger = xmon;
3624 __debugger_ipi = xmon_ipi;
3625 __debugger_bpt = xmon_bpt;
3626 __debugger_sstep = xmon_sstep;
3627 __debugger_iabr_match = xmon_iabr_match;
3628 __debugger_break_match = xmon_break_match;
3629 __debugger_fault_handler = xmon_fault_handler;
3630 } else {
3631 __debugger = NULL;
3632 __debugger_ipi = NULL;
3633 __debugger_bpt = NULL;
3634 __debugger_sstep = NULL;
3635 __debugger_iabr_match = NULL;
3636 __debugger_break_match = NULL;
3637 __debugger_fault_handler = NULL;
3638 }
3639}
3640
3641#ifdef CONFIG_MAGIC_SYSRQ
3642static void sysrq_handle_xmon(int key)
3643{
3644
3645 xmon_init(1);
3646 debugger(get_irq_regs());
3647 if (!xmon_on)
3648 xmon_init(0);
3649}
3650
3651static struct sysrq_key_op sysrq_xmon_op = {
3652 .handler = sysrq_handle_xmon,
3653 .help_msg = "xmon(x)",
3654 .action_msg = "Entering xmon",
3655};
3656
3657static int __init setup_xmon_sysrq(void)
3658{
3659 register_sysrq_key('x', &sysrq_xmon_op);
3660 return 0;
3661}
3662device_initcall(setup_xmon_sysrq);
3663#endif
3664
3665#ifdef CONFIG_DEBUG_FS
3666static void clear_all_bpt(void)
3667{
3668 int i;
3669
3670
3671 remove_bpts();
3672 remove_cpu_bpts();
3673
3674
3675 for (i = 0; i < NBPTS; ++i)
3676 bpts[i].enabled = 0;
3677
3678
3679 if (iabr || dabr.enabled) {
3680 iabr = NULL;
3681 dabr.enabled = 0;
3682 }
3683
3684 printf("xmon: All breakpoints cleared\n");
3685}
3686
3687static int xmon_dbgfs_set(void *data, u64 val)
3688{
3689 xmon_on = !!val;
3690 xmon_init(xmon_on);
3691
3692
3693 if (!xmon_on)
3694 clear_all_bpt();
3695 return 0;
3696}
3697
3698static int xmon_dbgfs_get(void *data, u64 *val)
3699{
3700 *val = xmon_on;
3701 return 0;
3702}
3703
3704DEFINE_SIMPLE_ATTRIBUTE(xmon_dbgfs_ops, xmon_dbgfs_get,
3705 xmon_dbgfs_set, "%llu\n");
3706
3707static int __init setup_xmon_dbgfs(void)
3708{
3709 debugfs_create_file("xmon", 0600, powerpc_debugfs_root, NULL,
3710 &xmon_dbgfs_ops);
3711 return 0;
3712}
3713device_initcall(setup_xmon_dbgfs);
3714#endif
3715
3716static int xmon_early __initdata;
3717
3718static int __init early_parse_xmon(char *p)
3719{
3720 if (!p || strncmp(p, "early", 5) == 0) {
3721
3722 xmon_init(1);
3723 xmon_early = 1;
3724 xmon_on = 1;
3725 } else if (strncmp(p, "on", 2) == 0) {
3726 xmon_init(1);
3727 xmon_on = 1;
3728 } else if (strncmp(p, "off", 3) == 0)
3729 xmon_on = 0;
3730 else
3731 return 1;
3732
3733 return 0;
3734}
3735early_param("xmon", early_parse_xmon);
3736
3737void __init xmon_setup(void)
3738{
3739 if (xmon_on)
3740 xmon_init(1);
3741 if (xmon_early)
3742 debugger(NULL);
3743}
3744
3745#ifdef CONFIG_SPU_BASE
3746
3747struct spu_info {
3748 struct spu *spu;
3749 u64 saved_mfc_sr1_RW;
3750 u32 saved_spu_runcntl_RW;
3751 unsigned long dump_addr;
3752 u8 stopped_ok;
3753};
3754
3755#define XMON_NUM_SPUS 16
3756
3757static struct spu_info spu_info[XMON_NUM_SPUS];
3758
3759void xmon_register_spus(struct list_head *list)
3760{
3761 struct spu *spu;
3762
3763 list_for_each_entry(spu, list, full_list) {
3764 if (spu->number >= XMON_NUM_SPUS) {
3765 WARN_ON(1);
3766 continue;
3767 }
3768
3769 spu_info[spu->number].spu = spu;
3770 spu_info[spu->number].stopped_ok = 0;
3771 spu_info[spu->number].dump_addr = (unsigned long)
3772 spu_info[spu->number].spu->local_store;
3773 }
3774}
3775
3776static void stop_spus(void)
3777{
3778 struct spu *spu;
3779 int i;
3780 u64 tmp;
3781
3782 for (i = 0; i < XMON_NUM_SPUS; i++) {
3783 if (!spu_info[i].spu)
3784 continue;
3785
3786 if (setjmp(bus_error_jmp) == 0) {
3787 catch_memory_errors = 1;
3788 sync();
3789
3790 spu = spu_info[i].spu;
3791
3792 spu_info[i].saved_spu_runcntl_RW =
3793 in_be32(&spu->problem->spu_runcntl_RW);
3794
3795 tmp = spu_mfc_sr1_get(spu);
3796 spu_info[i].saved_mfc_sr1_RW = tmp;
3797
3798 tmp &= ~MFC_STATE1_MASTER_RUN_CONTROL_MASK;
3799 spu_mfc_sr1_set(spu, tmp);
3800
3801 sync();
3802 __delay(200);
3803
3804 spu_info[i].stopped_ok = 1;
3805
3806 printf("Stopped spu %.2d (was %s)\n", i,
3807 spu_info[i].saved_spu_runcntl_RW ?
3808 "running" : "stopped");
3809 } else {
3810 catch_memory_errors = 0;
3811 printf("*** Error stopping spu %.2d\n", i);
3812 }
3813 catch_memory_errors = 0;
3814 }
3815}
3816
3817static void restart_spus(void)
3818{
3819 struct spu *spu;
3820 int i;
3821
3822 for (i = 0; i < XMON_NUM_SPUS; i++) {
3823 if (!spu_info[i].spu)
3824 continue;
3825
3826 if (!spu_info[i].stopped_ok) {
3827 printf("*** Error, spu %d was not successfully stopped"
3828 ", not restarting\n", i);
3829 continue;
3830 }
3831
3832 if (setjmp(bus_error_jmp) == 0) {
3833 catch_memory_errors = 1;
3834 sync();
3835
3836 spu = spu_info[i].spu;
3837 spu_mfc_sr1_set(spu, spu_info[i].saved_mfc_sr1_RW);
3838 out_be32(&spu->problem->spu_runcntl_RW,
3839 spu_info[i].saved_spu_runcntl_RW);
3840
3841 sync();
3842 __delay(200);
3843
3844 printf("Restarted spu %.2d\n", i);
3845 } else {
3846 catch_memory_errors = 0;
3847 printf("*** Error restarting spu %.2d\n", i);
3848 }
3849 catch_memory_errors = 0;
3850 }
3851}
3852
3853#define DUMP_WIDTH 23
3854#define DUMP_VALUE(format, field, value) \
3855do { \
3856 if (setjmp(bus_error_jmp) == 0) { \
3857 catch_memory_errors = 1; \
3858 sync(); \
3859 printf(" %-*s = "format"\n", DUMP_WIDTH, \
3860 #field, value); \
3861 sync(); \
3862 __delay(200); \
3863 } else { \
3864 catch_memory_errors = 0; \
3865 printf(" %-*s = *** Error reading field.\n", \
3866 DUMP_WIDTH, #field); \
3867 } \
3868 catch_memory_errors = 0; \
3869} while (0)
3870
3871#define DUMP_FIELD(obj, format, field) \
3872 DUMP_VALUE(format, field, obj->field)
3873
3874static void dump_spu_fields(struct spu *spu)
3875{
3876 printf("Dumping spu fields at address %p:\n", spu);
3877
3878 DUMP_FIELD(spu, "0x%x", number);
3879 DUMP_FIELD(spu, "%s", name);
3880 DUMP_FIELD(spu, "0x%lx", local_store_phys);
3881 DUMP_FIELD(spu, "0x%p", local_store);
3882 DUMP_FIELD(spu, "0x%lx", ls_size);
3883 DUMP_FIELD(spu, "0x%x", node);
3884 DUMP_FIELD(spu, "0x%lx", flags);
3885 DUMP_FIELD(spu, "%d", class_0_pending);
3886 DUMP_FIELD(spu, "0x%lx", class_0_dar);
3887 DUMP_FIELD(spu, "0x%lx", class_1_dar);
3888 DUMP_FIELD(spu, "0x%lx", class_1_dsisr);
3889 DUMP_FIELD(spu, "0x%lx", irqs[0]);
3890 DUMP_FIELD(spu, "0x%lx", irqs[1]);
3891 DUMP_FIELD(spu, "0x%lx", irqs[2]);
3892 DUMP_FIELD(spu, "0x%x", slb_replace);
3893 DUMP_FIELD(spu, "%d", pid);
3894 DUMP_FIELD(spu, "0x%p", mm);
3895 DUMP_FIELD(spu, "0x%p", ctx);
3896 DUMP_FIELD(spu, "0x%p", rq);
3897 DUMP_FIELD(spu, "0x%p", timestamp);
3898 DUMP_FIELD(spu, "0x%lx", problem_phys);
3899 DUMP_FIELD(spu, "0x%p", problem);
3900 DUMP_VALUE("0x%x", problem->spu_runcntl_RW,
3901 in_be32(&spu->problem->spu_runcntl_RW));
3902 DUMP_VALUE("0x%x", problem->spu_status_R,
3903 in_be32(&spu->problem->spu_status_R));
3904 DUMP_VALUE("0x%x", problem->spu_npc_RW,
3905 in_be32(&spu->problem->spu_npc_RW));
3906 DUMP_FIELD(spu, "0x%p", priv2);
3907 DUMP_FIELD(spu, "0x%p", pdata);
3908}
3909
3910int
3911spu_inst_dump(unsigned long adr, long count, int praddr)
3912{
3913 return generic_inst_dump(adr, count, praddr, print_insn_spu);
3914}
3915
3916static void dump_spu_ls(unsigned long num, int subcmd)
3917{
3918 unsigned long offset, addr, ls_addr;
3919
3920 if (setjmp(bus_error_jmp) == 0) {
3921 catch_memory_errors = 1;
3922 sync();
3923 ls_addr = (unsigned long)spu_info[num].spu->local_store;
3924 sync();
3925 __delay(200);
3926 } else {
3927 catch_memory_errors = 0;
3928 printf("*** Error: accessing spu info for spu %d\n", num);
3929 return;
3930 }
3931 catch_memory_errors = 0;
3932
3933 if (scanhex(&offset))
3934 addr = ls_addr + offset;
3935 else
3936 addr = spu_info[num].dump_addr;
3937
3938 if (addr >= ls_addr + LS_SIZE) {
3939 printf("*** Error: address outside of local store\n");
3940 return;
3941 }
3942
3943 switch (subcmd) {
3944 case 'i':
3945 addr += spu_inst_dump(addr, 16, 1);
3946 last_cmd = "sdi\n";
3947 break;
3948 default:
3949 prdump(addr, 64);
3950 addr += 64;
3951 last_cmd = "sd\n";
3952 break;
3953 }
3954
3955 spu_info[num].dump_addr = addr;
3956}
3957
3958static int do_spu_cmd(void)
3959{
3960 static unsigned long num = 0;
3961 int cmd, subcmd = 0;
3962
3963 cmd = inchar();
3964 switch (cmd) {
3965 case 's':
3966 stop_spus();
3967 break;
3968 case 'r':
3969 restart_spus();
3970 break;
3971 case 'd':
3972 subcmd = inchar();
3973 if (isxdigit(subcmd) || subcmd == '\n')
3974 termch = subcmd;
3975 case 'f':
3976 scanhex(&num);
3977 if (num >= XMON_NUM_SPUS || !spu_info[num].spu) {
3978 printf("*** Error: invalid spu number\n");
3979 return 0;
3980 }
3981
3982 switch (cmd) {
3983 case 'f':
3984 dump_spu_fields(spu_info[num].spu);
3985 break;
3986 default:
3987 dump_spu_ls(num, subcmd);
3988 break;
3989 }
3990
3991 break;
3992 default:
3993 return -1;
3994 }
3995
3996 return 0;
3997}
3998#else
3999static int do_spu_cmd(void)
4000{
4001 return -1;
4002}
4003#endif
4004