2 * Routines providing a simple monitor for use on the PowerMac.
4 * Copyright (C) 1996-2005 Paul Mackerras.
5 * Copyright (C) 2001 PPC64 Team, IBM Corp
6 * Copyrignt (C) 2006 Michael Ellerman, IBM Corp
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version
11 * 2 of the License, or (at your option) any later version.
13 #include <linux/errno.h>
14 #include <linux/sched.h>
15 #include <linux/smp.h>
17 #include <linux/reboot.h>
18 #include <linux/delay.h>
19 #include <linux/kallsyms.h>
20 #include <linux/kmsg_dump.h>
21 #include <linux/cpumask.h>
22 #include <linux/export.h>
23 #include <linux/sysrq.h>
24 #include <linux/interrupt.h>
25 #include <linux/irq.h>
26 #include <linux/bug.h>
27 #include <linux/nmi.h>
29 #include <asm/ptrace.h>
30 #include <asm/string.h>
32 #include <asm/machdep.h>
34 #include <asm/processor.h>
35 #include <asm/pgtable.h>
37 #include <asm/mmu_context.h>
38 #include <asm/cputable.h>
40 #include <asm/sstep.h>
41 #include <asm/irq_regs.h>
43 #include <asm/spu_priv1.h>
44 #include <asm/setjmp.h>
46 #include <asm/debug.h>
47 #include <asm/hw_breakpoint.h>
50 #include <asm/hvcall.h>
58 static cpumask_t cpus_in_xmon
= CPU_MASK_NONE
;
59 static unsigned long xmon_taken
= 1;
60 static int xmon_owner
;
64 #endif /* CONFIG_SMP */
66 static unsigned long in_xmon __read_mostly
= 0;
68 static unsigned long adrs
;
70 #define MAX_DUMP (128 * 1024)
71 static unsigned long ndump
= 64;
72 static unsigned long nidump
= 16;
73 static unsigned long ncsum
= 4096;
75 static char tmpstr
[128];
77 static long bus_error_jmp
[JMP_BUF_LEN
];
78 static int catch_memory_errors
;
79 static long *xmon_fault_jmp
[NR_CPUS
];
81 /* Breakpoint stuff */
83 unsigned long address
;
84 unsigned int instr
[2];
90 /* Bits in bpt.enabled */
91 #define BP_IABR_TE 1 /* IABR translation enabled */
97 static struct bpt bpts
[NBPTS
];
98 static struct bpt dabr
;
99 static struct bpt
*iabr
;
100 static unsigned bpinstr
= 0x7fe00008; /* trap */
102 #define BP_NUM(bp) ((bp) - bpts + 1)
105 static int cmds(struct pt_regs
*);
106 static int mread(unsigned long, void *, int);
107 static int mwrite(unsigned long, void *, int);
108 static int handle_fault(struct pt_regs
*);
109 static void byterev(unsigned char *, int);
110 static void memex(void);
111 static int bsesc(void);
112 static void dump(void);
113 static void prdump(unsigned long, long);
114 static int ppc_inst_dump(unsigned long, long, int);
115 static void dump_log_buf(void);
116 static void backtrace(struct pt_regs
*);
117 static void excprint(struct pt_regs
*);
118 static void prregs(struct pt_regs
*);
119 static void memops(int);
120 static void memlocate(void);
121 static void memzcan(void);
122 static void memdiffs(unsigned char *, unsigned char *, unsigned, unsigned);
124 int scanhex(unsigned long *valp
);
125 static void scannl(void);
126 static int hexdigit(int);
127 void getstring(char *, int);
128 static void flush_input(void);
129 static int inchar(void);
130 static void take_input(char *);
131 static unsigned long read_spr(int);
132 static void write_spr(int, unsigned long);
133 static void super_regs(void);
134 static void remove_bpts(void);
135 static void insert_bpts(void);
136 static void remove_cpu_bpts(void);
137 static void insert_cpu_bpts(void);
138 static struct bpt
*at_breakpoint(unsigned long pc
);
139 static struct bpt
*in_breakpoint_table(unsigned long pc
, unsigned long *offp
);
140 static int do_step(struct pt_regs
*);
141 static void bpt_cmds(void);
142 static void cacheflush(void);
143 static int cpu_cmd(void);
144 static void csum(void);
145 static void bootcmds(void);
146 static void proccall(void);
147 void dump_segments(void);
148 static void symbol_lookup(void);
149 static void xmon_show_stack(unsigned long sp
, unsigned long lr
,
151 static void xmon_print_symbol(unsigned long address
, const char *mid
,
153 static const char *getvecname(unsigned long vec
);
155 static int do_spu_cmd(void);
158 static void dump_tlb_44x(void);
160 #ifdef CONFIG_PPC_BOOK3E
161 static void dump_tlb_book3e(void);
164 static int xmon_no_auto_backtrace
;
166 extern void xmon_enter(void);
167 extern void xmon_leave(void);
175 #ifdef __LITTLE_ENDIAN__
176 #define GETWORD(v) (((v)[3] << 24) + ((v)[2] << 16) + ((v)[1] << 8) + (v)[0])
178 #define GETWORD(v) (((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
181 #define isxdigit(c) (('0' <= (c) && (c) <= '9') \
182 || ('a' <= (c) && (c) <= 'f') \
183 || ('A' <= (c) && (c) <= 'F'))
184 #define isalnum(c) (('0' <= (c) && (c) <= '9') \
185 || ('a' <= (c) && (c) <= 'z') \
186 || ('A' <= (c) && (c) <= 'Z'))
187 #define isspace(c) (c == ' ' || c == '\t' || c == 10 || c == 13 || c == 0)
189 static char *help_string
= "\
191 b show breakpoints\n\
192 bd set data breakpoint\n\
193 bi set instruction breakpoint\n\
194 bc clear breakpoint\n"
197 c print cpus stopped in xmon\n\
198 c# try to switch to cpu number h (in hex)\n"
203 di dump instructions\n\
204 df dump float values\n\
205 dd dump double values\n\
206 dl dump the kernel log buffer\n"
209 dp[#] dump paca for current cpu, or cpu #\n\
210 dpa dump paca for all possible cpus\n"
213 dr dump stream of raw bytes\n\
214 e print exception information\n\
216 la lookup symbol+offset of specified address\n\
217 ls lookup address of specified symbol\n\
218 m examine/change memory\n\
219 mm move a block of memory\n\
220 ms set a block of memory\n\
221 md compare two blocks of memory\n\
222 ml locate a block of memory\n\
223 mz zero a block of memory\n\
224 mi show information about memory allocation\n\
225 p call a procedure\n\
228 #ifdef CONFIG_SPU_BASE
229 " ss stop execution on all spus\n\
230 sr restore execution on stopped spus\n\
231 sf # dump spu fields for spu # (in hex)\n\
232 sd # dump spu local store for spu # (in hex)\n\
233 sdi # disassemble spu local store for spu # (in hex)\n"
235 " S print special registers\n\
237 x exit monitor and recover\n\
238 X exit monitor and dont recover\n"
239 #if defined(CONFIG_PPC64) && !defined(CONFIG_PPC_BOOK3E)
240 " u dump segment table or SLB\n"
241 #elif defined(CONFIG_PPC_STD_MMU_32)
242 " u dump segment registers\n"
243 #elif defined(CONFIG_44x) || defined(CONFIG_PPC_BOOK3E)
251 static struct pt_regs
*xmon_regs
;
253 static inline void sync(void)
255 asm volatile("sync; isync");
258 static inline void store_inst(void *p
)
260 asm volatile ("dcbst 0,%0; sync; icbi 0,%0; isync" : : "r" (p
));
263 static inline void cflush(void *p
)
265 asm volatile ("dcbf 0,%0; icbi 0,%0" : : "r" (p
));
268 static inline void cinval(void *p
)
270 asm volatile ("dcbi 0,%0; icbi 0,%0" : : "r" (p
));
274 * Disable surveillance (the service processor watchdog function)
275 * while we are in xmon.
276 * XXX we should re-enable it when we leave. :)
278 #define SURVEILLANCE_TOKEN 9000
280 static inline void disable_surveillance(void)
282 #ifdef CONFIG_PPC_PSERIES
283 /* Since this can't be a module, args should end up below 4GB. */
284 static struct rtas_args args
;
287 * At this point we have got all the cpus we can into
288 * xmon, so there is hopefully no other cpu calling RTAS
289 * at the moment, even though we don't take rtas.lock.
290 * If we did try to take rtas.lock there would be a
291 * real possibility of deadlock.
293 args
.token
= rtas_token("set-indicator");
294 if (args
.token
== RTAS_UNKNOWN_SERVICE
)
298 args
.rets
= &args
.args
[3];
299 args
.args
[0] = SURVEILLANCE_TOKEN
;
302 enter_rtas(__pa(&args
));
303 #endif /* CONFIG_PPC_PSERIES */
307 static int xmon_speaker
;
309 static void get_output_lock(void)
311 int me
= smp_processor_id() + 0x100;
312 int last_speaker
= 0, prev
;
315 if (xmon_speaker
== me
)
319 last_speaker
= cmpxchg(&xmon_speaker
, 0, me
);
320 if (last_speaker
== 0)
324 * Wait a full second for the lock, we might be on a slow
325 * console, but check every 100us.
328 while (xmon_speaker
== last_speaker
) {
334 /* hostile takeover */
335 prev
= cmpxchg(&xmon_speaker
, last_speaker
, me
);
336 if (prev
== last_speaker
)
343 static void release_output_lock(void)
348 int cpus_are_in_xmon(void)
350 return !cpumask_empty(&cpus_in_xmon
);
354 static inline int unrecoverable_excp(struct pt_regs
*regs
)
356 #if defined(CONFIG_4xx) || defined(CONFIG_PPC_BOOK3E)
357 /* We have no MSR_RI bit on 4xx or Book3e, so we simply return false */
360 return ((regs
->msr
& MSR_RI
) == 0);
364 static int xmon_core(struct pt_regs
*regs
, int fromipi
)
368 long recurse_jmp
[JMP_BUF_LEN
];
369 unsigned long offset
;
374 unsigned long timeout
;
377 local_irq_save(flags
);
380 bp
= in_breakpoint_table(regs
->nip
, &offset
);
382 regs
->nip
= bp
->address
+ offset
;
383 atomic_dec(&bp
->ref_count
);
389 cpu
= smp_processor_id();
390 if (cpumask_test_cpu(cpu
, &cpus_in_xmon
)) {
393 printf("cpu 0x%x: Exception %lx %s in xmon, "
394 "returning to main loop\n",
395 cpu
, regs
->trap
, getvecname(TRAP(regs
)));
396 release_output_lock();
397 longjmp(xmon_fault_jmp
[cpu
], 1);
400 if (setjmp(recurse_jmp
) != 0) {
401 if (!in_xmon
|| !xmon_gate
) {
403 printf("xmon: WARNING: bad recursive fault "
404 "on cpu 0x%x\n", cpu
);
405 release_output_lock();
408 secondary
= !(xmon_taken
&& cpu
== xmon_owner
);
412 xmon_fault_jmp
[cpu
] = recurse_jmp
;
415 if ((regs
->msr
& (MSR_IR
|MSR_PR
|MSR_64BIT
)) == (MSR_IR
|MSR_64BIT
))
416 bp
= at_breakpoint(regs
->nip
);
417 if (bp
|| unrecoverable_excp(regs
))
424 printf("cpu 0x%x stopped at breakpoint 0x%lx (",
426 xmon_print_symbol(regs
->nip
, " ", ")\n");
428 if (unrecoverable_excp(regs
))
429 printf("WARNING: exception is not recoverable, "
431 release_output_lock();
434 cpumask_set_cpu(cpu
, &cpus_in_xmon
);
438 while (secondary
&& !xmon_gate
) {
442 secondary
= test_and_set_bit(0, &in_xmon
);
447 if (!secondary
&& !xmon_gate
) {
448 /* we are the first cpu to come in */
449 /* interrupt other cpu(s) */
450 int ncpus
= num_online_cpus();
455 smp_send_debugger_break();
456 /* wait for other cpus to come in */
457 for (timeout
= 100000000; timeout
!= 0; --timeout
) {
458 if (cpumask_weight(&cpus_in_xmon
) >= ncpus
)
464 disable_surveillance();
465 /* for breakpoint or single step, print the current instr. */
466 if (bp
|| TRAP(regs
) == 0xd00)
467 ppc_inst_dump(regs
->nip
, 1, 0);
468 printf("enter ? for help\n");
477 if (cpu
== xmon_owner
) {
478 if (!test_and_set_bit(0, &xmon_taken
)) {
483 while (cpu
== xmon_owner
)
497 /* have switched to some other cpu */
502 cpumask_clear_cpu(cpu
, &cpus_in_xmon
);
503 xmon_fault_jmp
[cpu
] = NULL
;
505 /* UP is simple... */
507 printf("Exception %lx %s in xmon, returning to main loop\n",
508 regs
->trap
, getvecname(TRAP(regs
)));
509 longjmp(xmon_fault_jmp
[0], 1);
511 if (setjmp(recurse_jmp
) == 0) {
512 xmon_fault_jmp
[0] = recurse_jmp
;
516 bp
= at_breakpoint(regs
->nip
);
518 printf("Stopped at breakpoint %lx (", BP_NUM(bp
));
519 xmon_print_symbol(regs
->nip
, " ", ")\n");
521 if (unrecoverable_excp(regs
))
522 printf("WARNING: exception is not recoverable, "
525 disable_surveillance();
526 /* for breakpoint or single step, print the current instr. */
527 if (bp
|| TRAP(regs
) == 0xd00)
528 ppc_inst_dump(regs
->nip
, 1, 0);
529 printf("enter ? for help\n");
539 if (regs
->msr
& MSR_DE
) {
540 bp
= at_breakpoint(regs
->nip
);
542 regs
->nip
= (unsigned long) &bp
->instr
[0];
543 atomic_inc(&bp
->ref_count
);
547 if ((regs
->msr
& (MSR_IR
|MSR_PR
|MSR_64BIT
)) == (MSR_IR
|MSR_64BIT
)) {
548 bp
= at_breakpoint(regs
->nip
);
550 int stepped
= emulate_step(regs
, bp
->instr
[0]);
552 regs
->nip
= (unsigned long) &bp
->instr
[0];
553 atomic_inc(&bp
->ref_count
);
554 } else if (stepped
< 0) {
555 printf("Couldn't single-step %s instruction\n",
556 (IS_RFID(bp
->instr
[0])? "rfid": "mtmsrd"));
563 touch_nmi_watchdog();
564 local_irq_restore(flags
);
566 return cmd
!= 'X' && cmd
!= EOF
;
569 int xmon(struct pt_regs
*excp
)
574 ppc_save_regs(®s
);
578 return xmon_core(excp
, 0);
582 irqreturn_t
xmon_irq(int irq
, void *d
)
585 local_irq_save(flags
);
586 printf("Keyboard interrupt\n");
587 xmon(get_irq_regs());
588 local_irq_restore(flags
);
592 static int xmon_bpt(struct pt_regs
*regs
)
595 unsigned long offset
;
597 if ((regs
->msr
& (MSR_IR
|MSR_PR
|MSR_64BIT
)) != (MSR_IR
|MSR_64BIT
))
600 /* Are we at the trap at bp->instr[1] for some bp? */
601 bp
= in_breakpoint_table(regs
->nip
, &offset
);
602 if (bp
!= NULL
&& offset
== 4) {
603 regs
->nip
= bp
->address
+ 4;
604 atomic_dec(&bp
->ref_count
);
608 /* Are we at a breakpoint? */
609 bp
= at_breakpoint(regs
->nip
);
618 static int xmon_sstep(struct pt_regs
*regs
)
626 static int xmon_break_match(struct pt_regs
*regs
)
628 if ((regs
->msr
& (MSR_IR
|MSR_PR
|MSR_64BIT
)) != (MSR_IR
|MSR_64BIT
))
630 if (dabr
.enabled
== 0)
636 static int xmon_iabr_match(struct pt_regs
*regs
)
638 if ((regs
->msr
& (MSR_IR
|MSR_PR
|MSR_64BIT
)) != (MSR_IR
|MSR_64BIT
))
646 static int xmon_ipi(struct pt_regs
*regs
)
649 if (in_xmon
&& !cpumask_test_cpu(smp_processor_id(), &cpus_in_xmon
))
655 static int xmon_fault_handler(struct pt_regs
*regs
)
658 unsigned long offset
;
660 if (in_xmon
&& catch_memory_errors
)
661 handle_fault(regs
); /* doesn't return */
663 if ((regs
->msr
& (MSR_IR
|MSR_PR
|MSR_64BIT
)) == (MSR_IR
|MSR_64BIT
)) {
664 bp
= in_breakpoint_table(regs
->nip
, &offset
);
666 regs
->nip
= bp
->address
+ offset
;
667 atomic_dec(&bp
->ref_count
);
674 static struct bpt
*at_breakpoint(unsigned long pc
)
680 for (i
= 0; i
< NBPTS
; ++i
, ++bp
)
681 if (bp
->enabled
&& pc
== bp
->address
)
686 static struct bpt
*in_breakpoint_table(unsigned long nip
, unsigned long *offp
)
690 off
= nip
- (unsigned long) bpts
;
691 if (off
>= sizeof(bpts
))
693 off
%= sizeof(struct bpt
);
694 if (off
!= offsetof(struct bpt
, instr
[0])
695 && off
!= offsetof(struct bpt
, instr
[1]))
697 *offp
= off
- offsetof(struct bpt
, instr
[0]);
698 return (struct bpt
*) (nip
- off
);
701 static struct bpt
*new_breakpoint(unsigned long a
)
706 bp
= at_breakpoint(a
);
710 for (bp
= bpts
; bp
< &bpts
[NBPTS
]; ++bp
) {
711 if (!bp
->enabled
&& atomic_read(&bp
->ref_count
) == 0) {
713 bp
->instr
[1] = bpinstr
;
714 store_inst(&bp
->instr
[1]);
719 printf("Sorry, no free breakpoints. Please clear one first.\n");
723 static void insert_bpts(void)
729 for (i
= 0; i
< NBPTS
; ++i
, ++bp
) {
730 if ((bp
->enabled
& (BP_TRAP
|BP_IABR
)) == 0)
732 if (mread(bp
->address
, &bp
->instr
[0], 4) != 4) {
733 printf("Couldn't read instruction at %lx, "
734 "disabling breakpoint there\n", bp
->address
);
738 if (IS_MTMSRD(bp
->instr
[0]) || IS_RFID(bp
->instr
[0])) {
739 printf("Breakpoint at %lx is on an mtmsrd or rfid "
740 "instruction, disabling it\n", bp
->address
);
744 store_inst(&bp
->instr
[0]);
745 if (bp
->enabled
& BP_IABR
)
747 if (mwrite(bp
->address
, &bpinstr
, 4) != 4) {
748 printf("Couldn't write instruction at %lx, "
749 "disabling breakpoint there\n", bp
->address
);
750 bp
->enabled
&= ~BP_TRAP
;
753 store_inst((void *)bp
->address
);
757 static void insert_cpu_bpts(void)
759 struct arch_hw_breakpoint brk
;
762 brk
.address
= dabr
.address
;
763 brk
.type
= (dabr
.enabled
& HW_BRK_TYPE_DABR
) | HW_BRK_TYPE_PRIV_ALL
;
765 __set_breakpoint(&brk
);
767 if (iabr
&& cpu_has_feature(CPU_FTR_IABR
))
768 mtspr(SPRN_IABR
, iabr
->address
769 | (iabr
->enabled
& (BP_IABR
|BP_IABR_TE
)));
772 static void remove_bpts(void)
779 for (i
= 0; i
< NBPTS
; ++i
, ++bp
) {
780 if ((bp
->enabled
& (BP_TRAP
|BP_IABR
)) != BP_TRAP
)
782 if (mread(bp
->address
, &instr
, 4) == 4
784 && mwrite(bp
->address
, &bp
->instr
, 4) != 4)
785 printf("Couldn't remove breakpoint at %lx\n",
788 store_inst((void *)bp
->address
);
792 static void remove_cpu_bpts(void)
794 hw_breakpoint_disable();
795 if (cpu_has_feature(CPU_FTR_IABR
))
799 /* Command interpreting routine */
800 static char *last_cmd
;
803 cmds(struct pt_regs
*excp
)
810 if (!xmon_no_auto_backtrace
) {
811 xmon_no_auto_backtrace
= 1;
812 xmon_show_stack(excp
->gpr
[1], excp
->link
, excp
->nip
);
817 printf("%x:", smp_processor_id());
818 #endif /* CONFIG_SMP */
824 if (last_cmd
== NULL
)
826 take_input(last_cmd
);
860 prregs(excp
); /* print regs */
875 if (do_spu_cmd() == 0)
884 printf(" <no input ...>\n");
888 xmon_puts(help_string
);
906 #ifdef CONFIG_PPC_STD_MMU
910 #elif defined(CONFIG_4xx)
914 #elif defined(CONFIG_PPC_BOOK3E)
920 printf("Unrecognized command: ");
922 if (' ' < cmd
&& cmd
<= '~')
925 printf("\\x%x", cmd
);
927 } while (cmd
!= '\n');
928 printf(" (type ? for help)\n");
935 static int do_step(struct pt_regs
*regs
)
938 mtspr(SPRN_DBCR0
, mfspr(SPRN_DBCR0
) | DBCR0_IC
| DBCR0_IDM
);
943 * Step a single instruction.
944 * Some instructions we emulate, others we execute with MSR_SE set.
946 static int do_step(struct pt_regs
*regs
)
951 /* check we are in 64-bit kernel mode, translation enabled */
952 if ((regs
->msr
& (MSR_64BIT
|MSR_PR
|MSR_IR
)) == (MSR_64BIT
|MSR_IR
)) {
953 if (mread(regs
->nip
, &instr
, 4) == 4) {
954 stepped
= emulate_step(regs
, instr
);
956 printf("Couldn't single-step %s instruction\n",
957 (IS_RFID(instr
)? "rfid": "mtmsrd"));
961 regs
->trap
= 0xd00 | (regs
->trap
& 1);
962 printf("stepped to ");
963 xmon_print_symbol(regs
->nip
, " ", "\n");
964 ppc_inst_dump(regs
->nip
, 1, 0);
974 static void bootcmds(void)
980 ppc_md
.restart(NULL
);
987 static int cpu_cmd(void)
990 unsigned long cpu
, first_cpu
, last_cpu
;
993 if (!scanhex(&cpu
)) {
994 /* print cpus waiting or in xmon */
995 printf("cpus stopped:");
996 last_cpu
= first_cpu
= NR_CPUS
;
997 for_each_possible_cpu(cpu
) {
998 if (cpumask_test_cpu(cpu
, &cpus_in_xmon
)) {
999 if (cpu
== last_cpu
+ 1) {
1002 if (last_cpu
!= first_cpu
)
1003 printf("-0x%lx", last_cpu
);
1004 last_cpu
= first_cpu
= cpu
;
1005 printf(" 0x%lx", cpu
);
1009 if (last_cpu
!= first_cpu
)
1010 printf("-0x%lx", last_cpu
);
1014 /* try to switch to cpu specified */
1015 if (!cpumask_test_cpu(cpu
, &cpus_in_xmon
)) {
1016 printf("cpu 0x%x isn't in xmon\n", cpu
);
1023 while (!xmon_taken
) {
1024 if (--timeout
== 0) {
1025 if (test_and_set_bit(0, &xmon_taken
))
1027 /* take control back */
1029 xmon_owner
= smp_processor_id();
1030 printf("cpu 0x%x didn't take control\n", cpu
);
1038 #endif /* CONFIG_SMP */
1041 static unsigned short fcstab
[256] = {
1042 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
1043 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
1044 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
1045 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
1046 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
1047 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
1048 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
1049 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
1050 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
1051 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
1052 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
1053 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
1054 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
1055 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
1056 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
1057 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
1058 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
1059 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
1060 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
1061 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
1062 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
1063 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
1064 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
1065 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
1066 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
1067 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
1068 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
1069 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
1070 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
1071 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
1072 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
1073 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
1076 #define FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
1085 if (!scanhex(&adrs
))
1087 if (!scanhex(&ncsum
))
1090 for (i
= 0; i
< ncsum
; ++i
) {
1091 if (mread(adrs
+i
, &v
, 1) == 0) {
1092 printf("csum stopped at "REG
"\n", adrs
+i
);
1097 printf("%x\n", fcs
);
1101 * Check if this is a suitable place to put a breakpoint.
1103 static long check_bp_loc(unsigned long addr
)
1108 if (!is_kernel_addr(addr
)) {
1109 printf("Breakpoints may only be placed at kernel addresses\n");
1112 if (!mread(addr
, &instr
, sizeof(instr
))) {
1113 printf("Can't read instruction at address %lx\n", addr
);
1116 if (IS_MTMSRD(instr
) || IS_RFID(instr
)) {
1117 printf("Breakpoints may not be placed on mtmsrd or rfid "
1124 static char *breakpoint_help_string
=
1125 "Breakpoint command usage:\n"
1126 "b show breakpoints\n"
1127 "b <addr> [cnt] set breakpoint at given instr addr\n"
1128 "bc clear all breakpoints\n"
1129 "bc <n/addr> clear breakpoint number n or at addr\n"
1130 "bi <addr> [cnt] set hardware instr breakpoint (POWER3/RS64 only)\n"
1131 "bd <addr> [cnt] set hardware data breakpoint\n"
1141 const char badaddr
[] = "Only kernel addresses are permitted "
1142 "for breakpoints\n";
1147 case 'd': /* bd - hardware data breakpoint */
1152 else if (cmd
== 'w')
1158 if (scanhex(&dabr
.address
)) {
1159 if (!is_kernel_addr(dabr
.address
)) {
1163 dabr
.address
&= ~HW_BRK_TYPE_DABR
;
1164 dabr
.enabled
= mode
| BP_DABR
;
1168 case 'i': /* bi - hardware instr breakpoint */
1169 if (!cpu_has_feature(CPU_FTR_IABR
)) {
1170 printf("Hardware instruction breakpoint "
1171 "not supported on this cpu\n");
1175 iabr
->enabled
&= ~(BP_IABR
| BP_IABR_TE
);
1180 if (!check_bp_loc(a
))
1182 bp
= new_breakpoint(a
);
1184 bp
->enabled
|= BP_IABR
| BP_IABR_TE
;
1192 /* clear all breakpoints */
1193 for (i
= 0; i
< NBPTS
; ++i
)
1194 bpts
[i
].enabled
= 0;
1197 printf("All breakpoints cleared\n");
1201 if (a
<= NBPTS
&& a
>= 1) {
1202 /* assume a breakpoint number */
1203 bp
= &bpts
[a
-1]; /* bp nums are 1 based */
1205 /* assume a breakpoint address */
1206 bp
= at_breakpoint(a
);
1208 printf("No breakpoint at %lx\n", a
);
1213 printf("Cleared breakpoint %lx (", BP_NUM(bp
));
1214 xmon_print_symbol(bp
->address
, " ", ")\n");
1222 printf(breakpoint_help_string
);
1227 /* print all breakpoints */
1228 printf(" type address\n");
1230 printf(" data "REG
" [", dabr
.address
);
1231 if (dabr
.enabled
& 1)
1233 if (dabr
.enabled
& 2)
1237 for (bp
= bpts
; bp
< &bpts
[NBPTS
]; ++bp
) {
1240 printf("%2x %s ", BP_NUM(bp
),
1241 (bp
->enabled
& BP_IABR
)? "inst": "trap");
1242 xmon_print_symbol(bp
->address
, " ", "\n");
1247 if (!check_bp_loc(a
))
1249 bp
= new_breakpoint(a
);
1251 bp
->enabled
|= BP_TRAP
;
1256 /* Very cheap human name for vector lookup. */
1258 const char *getvecname(unsigned long vec
)
1263 case 0x100: ret
= "(System Reset)"; break;
1264 case 0x200: ret
= "(Machine Check)"; break;
1265 case 0x300: ret
= "(Data Access)"; break;
1266 case 0x380: ret
= "(Data SLB Access)"; break;
1267 case 0x400: ret
= "(Instruction Access)"; break;
1268 case 0x480: ret
= "(Instruction SLB Access)"; break;
1269 case 0x500: ret
= "(Hardware Interrupt)"; break;
1270 case 0x600: ret
= "(Alignment)"; break;
1271 case 0x700: ret
= "(Program Check)"; break;
1272 case 0x800: ret
= "(FPU Unavailable)"; break;
1273 case 0x900: ret
= "(Decrementer)"; break;
1274 case 0x980: ret
= "(Hypervisor Decrementer)"; break;
1275 case 0xa00: ret
= "(Doorbell)"; break;
1276 case 0xc00: ret
= "(System Call)"; break;
1277 case 0xd00: ret
= "(Single Step)"; break;
1278 case 0xe40: ret
= "(Emulation Assist)"; break;
1279 case 0xe60: ret
= "(HMI)"; break;
1280 case 0xe80: ret
= "(Hypervisor Doorbell)"; break;
1281 case 0xf00: ret
= "(Performance Monitor)"; break;
1282 case 0xf20: ret
= "(Altivec Unavailable)"; break;
1283 case 0x1300: ret
= "(Instruction Breakpoint)"; break;
1284 case 0x1500: ret
= "(Denormalisation)"; break;
1285 case 0x1700: ret
= "(Altivec Assist)"; break;
1291 static void get_function_bounds(unsigned long pc
, unsigned long *startp
,
1292 unsigned long *endp
)
1294 unsigned long size
, offset
;
1297 *startp
= *endp
= 0;
1300 if (setjmp(bus_error_jmp
) == 0) {
1301 catch_memory_errors
= 1;
1303 name
= kallsyms_lookup(pc
, &size
, &offset
, NULL
, tmpstr
);
1305 *startp
= pc
- offset
;
1306 *endp
= pc
- offset
+ size
;
1310 catch_memory_errors
= 0;
1313 #define LRSAVE_OFFSET (STACK_FRAME_LR_SAVE * sizeof(unsigned long))
1314 #define MARKER_OFFSET (STACK_FRAME_MARKER * sizeof(unsigned long))
1316 static void xmon_show_stack(unsigned long sp
, unsigned long lr
,
1319 int max_to_print
= 64;
1321 unsigned long newsp
;
1322 unsigned long marker
;
1323 struct pt_regs regs
;
1325 while (max_to_print
--) {
1326 if (sp
< PAGE_OFFSET
) {
1328 printf("SP (%lx) is in userspace\n", sp
);
1332 if (!mread(sp
+ LRSAVE_OFFSET
, &ip
, sizeof(unsigned long))
1333 || !mread(sp
, &newsp
, sizeof(unsigned long))) {
1334 printf("Couldn't read stack frame at %lx\n", sp
);
1339 * For the first stack frame, try to work out if
1340 * LR and/or the saved LR value in the bottommost
1341 * stack frame are valid.
1343 if ((pc
| lr
) != 0) {
1344 unsigned long fnstart
, fnend
;
1345 unsigned long nextip
;
1348 get_function_bounds(pc
, &fnstart
, &fnend
);
1351 mread(newsp
+ LRSAVE_OFFSET
, &nextip
,
1352 sizeof(unsigned long));
1354 if (lr
< PAGE_OFFSET
1355 || (fnstart
<= lr
&& lr
< fnend
))
1357 } else if (lr
== nextip
) {
1359 } else if (lr
>= PAGE_OFFSET
1360 && !(fnstart
<= lr
&& lr
< fnend
)) {
1361 printf("[link register ] ");
1362 xmon_print_symbol(lr
, " ", "\n");
1365 printf("["REG
"] ", sp
);
1366 xmon_print_symbol(ip
, " ", " (unreliable)\n");
1371 printf("["REG
"] ", sp
);
1372 xmon_print_symbol(ip
, " ", "\n");
1375 /* Look for "regshere" marker to see if this is
1376 an exception frame. */
1377 if (mread(sp
+ MARKER_OFFSET
, &marker
, sizeof(unsigned long))
1378 && marker
== STACK_FRAME_REGS_MARKER
) {
1379 if (mread(sp
+ STACK_FRAME_OVERHEAD
, ®s
, sizeof(regs
))
1381 printf("Couldn't read registers at %lx\n",
1382 sp
+ STACK_FRAME_OVERHEAD
);
1385 printf("--- Exception: %lx %s at ", regs
.trap
,
1386 getvecname(TRAP(®s
)));
1389 xmon_print_symbol(pc
, " ", "\n");
1399 static void backtrace(struct pt_regs
*excp
)
1404 xmon_show_stack(sp
, 0, 0);
1406 xmon_show_stack(excp
->gpr
[1], excp
->link
, excp
->nip
);
1410 static void print_bug_trap(struct pt_regs
*regs
)
1413 const struct bug_entry
*bug
;
1416 if (regs
->msr
& MSR_PR
)
1417 return; /* not in kernel */
1418 addr
= regs
->nip
; /* address of trap instruction */
1419 if (addr
< PAGE_OFFSET
)
1421 bug
= find_bug(regs
->nip
);
1424 if (is_warning_bug(bug
))
1427 #ifdef CONFIG_DEBUG_BUGVERBOSE
1428 printf("kernel BUG at %s:%u!\n",
1429 bug
->file
, bug
->line
);
1431 printf("kernel BUG at %p!\n", (void *)bug
->bug_addr
);
1433 #endif /* CONFIG_BUG */
1436 static void excprint(struct pt_regs
*fp
)
1441 printf("cpu 0x%x: ", smp_processor_id());
1442 #endif /* CONFIG_SMP */
1445 printf("Vector: %lx %s at [%lx]\n", fp
->trap
, getvecname(trap
), fp
);
1447 xmon_print_symbol(fp
->nip
, ": ", "\n");
1449 printf(" lr: ", fp
->link
);
1450 xmon_print_symbol(fp
->link
, ": ", "\n");
1452 printf(" sp: %lx\n", fp
->gpr
[1]);
1453 printf(" msr: %lx\n", fp
->msr
);
1455 if (trap
== 0x300 || trap
== 0x380 || trap
== 0x600 || trap
== 0x200) {
1456 printf(" dar: %lx\n", fp
->dar
);
1458 printf(" dsisr: %lx\n", fp
->dsisr
);
1461 printf(" current = 0x%lx\n", current
);
1463 printf(" paca = 0x%lx\t softe: %d\t irq_happened: 0x%02x\n",
1464 local_paca
, local_paca
->soft_enabled
, local_paca
->irq_happened
);
1467 printf(" pid = %ld, comm = %s\n",
1468 current
->pid
, current
->comm
);
1475 static void prregs(struct pt_regs
*fp
)
1479 struct pt_regs regs
;
1481 if (scanhex(&base
)) {
1482 if (setjmp(bus_error_jmp
) == 0) {
1483 catch_memory_errors
= 1;
1485 regs
= *(struct pt_regs
*)base
;
1489 catch_memory_errors
= 0;
1490 printf("*** Error reading registers from "REG
"\n",
1494 catch_memory_errors
= 0;
1499 if (FULL_REGS(fp
)) {
1500 for (n
= 0; n
< 16; ++n
)
1501 printf("R%.2ld = "REG
" R%.2ld = "REG
"\n",
1502 n
, fp
->gpr
[n
], n
+16, fp
->gpr
[n
+16]);
1504 for (n
= 0; n
< 7; ++n
)
1505 printf("R%.2ld = "REG
" R%.2ld = "REG
"\n",
1506 n
, fp
->gpr
[n
], n
+7, fp
->gpr
[n
+7]);
1509 for (n
= 0; n
< 32; ++n
) {
1510 printf("R%.2d = %.8x%s", n
, fp
->gpr
[n
],
1511 (n
& 3) == 3? "\n": " ");
1512 if (n
== 12 && !FULL_REGS(fp
)) {
1519 xmon_print_symbol(fp
->nip
, " ", "\n");
1520 if (TRAP(fp
) != 0xc00 && cpu_has_feature(CPU_FTR_CFAR
)) {
1522 xmon_print_symbol(fp
->orig_gpr3
, " ", "\n");
1525 xmon_print_symbol(fp
->link
, " ", "\n");
1526 printf("msr = "REG
" cr = %.8lx\n", fp
->msr
, fp
->ccr
);
1527 printf("ctr = "REG
" xer = "REG
" trap = %4lx\n",
1528 fp
->ctr
, fp
->xer
, fp
->trap
);
1530 if (trap
== 0x300 || trap
== 0x380 || trap
== 0x600)
1531 printf("dar = "REG
" dsisr = %.8lx\n", fp
->dar
, fp
->dsisr
);
1534 static void cacheflush(void)
1537 unsigned long nflush
;
1542 scanhex((void *)&adrs
);
1547 nflush
= (nflush
+ L1_CACHE_BYTES
- 1) / L1_CACHE_BYTES
;
1548 if (setjmp(bus_error_jmp
) == 0) {
1549 catch_memory_errors
= 1;
1553 for (; nflush
> 0; --nflush
, adrs
+= L1_CACHE_BYTES
)
1554 cflush((void *) adrs
);
1556 for (; nflush
> 0; --nflush
, adrs
+= L1_CACHE_BYTES
)
1557 cinval((void *) adrs
);
1560 /* wait a little while to see if we get a machine check */
1563 catch_memory_errors
= 0;
1566 static unsigned long
1569 unsigned int instrs
[2];
1570 unsigned long (*code
)(void);
1571 unsigned long ret
= -1UL;
1573 unsigned long opd
[3];
1575 opd
[0] = (unsigned long)instrs
;
1578 code
= (unsigned long (*)(void)) opd
;
1580 code
= (unsigned long (*)(void)) instrs
;
1583 /* mfspr r3,n; blr */
1584 instrs
[0] = 0x7c6002a6 + ((n
& 0x1F) << 16) + ((n
& 0x3e0) << 6);
1585 instrs
[1] = 0x4e800020;
1587 store_inst(instrs
+1);
1589 if (setjmp(bus_error_jmp
) == 0) {
1590 catch_memory_errors
= 1;
1596 /* wait a little while to see if we get a machine check */
1605 write_spr(int n
, unsigned long val
)
1607 unsigned int instrs
[2];
1608 unsigned long (*code
)(unsigned long);
1610 unsigned long opd
[3];
1612 opd
[0] = (unsigned long)instrs
;
1615 code
= (unsigned long (*)(unsigned long)) opd
;
1617 code
= (unsigned long (*)(unsigned long)) instrs
;
1620 instrs
[0] = 0x7c6003a6 + ((n
& 0x1F) << 16) + ((n
& 0x3e0) << 6);
1621 instrs
[1] = 0x4e800020;
1623 store_inst(instrs
+1);
1625 if (setjmp(bus_error_jmp
) == 0) {
1626 catch_memory_errors
= 1;
1632 /* wait a little while to see if we get a machine check */
1638 static unsigned long regno
;
1639 extern char exc_prolog
;
1640 extern char dec_exc
;
1642 static void super_regs(void)
1649 unsigned long sp
, toc
;
1650 asm("mr %0,1" : "=r" (sp
) :);
1651 asm("mr %0,2" : "=r" (toc
) :);
1653 printf("msr = "REG
" sprg0= "REG
"\n",
1654 mfmsr(), mfspr(SPRN_SPRG0
));
1655 printf("pvr = "REG
" sprg1= "REG
"\n",
1656 mfspr(SPRN_PVR
), mfspr(SPRN_SPRG1
));
1657 printf("dec = "REG
" sprg2= "REG
"\n",
1658 mfspr(SPRN_DEC
), mfspr(SPRN_SPRG2
));
1659 printf("sp = "REG
" sprg3= "REG
"\n", sp
, mfspr(SPRN_SPRG3
));
1660 printf("toc = "REG
" dar = "REG
"\n", toc
, mfspr(SPRN_DAR
));
1668 val
= read_spr(regno
);
1670 write_spr(regno
, val
);
1673 printf("spr %lx = %lx\n", regno
, read_spr(regno
));
1680 * Stuff for reading and writing memory safely
1683 mread(unsigned long adrs
, void *buf
, int size
)
1689 if (setjmp(bus_error_jmp
) == 0) {
1690 catch_memory_errors
= 1;
1696 *(u16
*)q
= *(u16
*)p
;
1699 *(u32
*)q
= *(u32
*)p
;
1702 *(u64
*)q
= *(u64
*)p
;
1705 for( ; n
< size
; ++n
) {
1711 /* wait a little while to see if we get a machine check */
1715 catch_memory_errors
= 0;
1720 mwrite(unsigned long adrs
, void *buf
, int size
)
1726 if (setjmp(bus_error_jmp
) == 0) {
1727 catch_memory_errors
= 1;
1733 *(u16
*)p
= *(u16
*)q
;
1736 *(u32
*)p
= *(u32
*)q
;
1739 *(u64
*)p
= *(u64
*)q
;
1742 for ( ; n
< size
; ++n
) {
1748 /* wait a little while to see if we get a machine check */
1752 printf("*** Error writing address "REG
"\n", adrs
+ n
);
1754 catch_memory_errors
= 0;
1758 static int fault_type
;
1759 static int fault_except
;
1760 static char *fault_chars
[] = { "--", "**", "##" };
1762 static int handle_fault(struct pt_regs
*regs
)
1764 fault_except
= TRAP(regs
);
1765 switch (TRAP(regs
)) {
1777 longjmp(bus_error_jmp
, 1);
1782 #define SWAP(a, b, t) ((t) = (a), (a) = (b), (b) = (t))
1785 byterev(unsigned char *val
, int size
)
1791 SWAP(val
[0], val
[1], t
);
1794 SWAP(val
[0], val
[3], t
);
1795 SWAP(val
[1], val
[2], t
);
1797 case 8: /* is there really any use for this? */
1798 SWAP(val
[0], val
[7], t
);
1799 SWAP(val
[1], val
[6], t
);
1800 SWAP(val
[2], val
[5], t
);
1801 SWAP(val
[3], val
[4], t
);
1809 static char *memex_help_string
=
1810 "Memory examine command usage:\n"
1811 "m [addr] [flags] examine/change memory\n"
1812 " addr is optional. will start where left off.\n"
1813 " flags may include chars from this set:\n"
1814 " b modify by bytes (default)\n"
1815 " w modify by words (2 byte)\n"
1816 " l modify by longs (4 byte)\n"
1817 " d modify by doubleword (8 byte)\n"
1818 " r toggle reverse byte order mode\n"
1819 " n do not read memory (for i/o spaces)\n"
1820 " . ok to read (default)\n"
1821 "NOTE: flags are saved as defaults\n"
1824 static char *memex_subcmd_help_string
=
1825 "Memory examine subcommands:\n"
1826 " hexval write this val to current location\n"
1827 " 'string' write chars from string to this location\n"
1828 " ' increment address\n"
1829 " ^ decrement address\n"
1830 " / increment addr by 0x10. //=0x100, ///=0x1000, etc\n"
1831 " \\ decrement addr by 0x10. \\\\=0x100, \\\\\\=0x1000, etc\n"
1832 " ` clear no-read flag\n"
1833 " ; stay at this addr\n"
1834 " v change to byte mode\n"
1835 " w change to word (2 byte) mode\n"
1836 " l change to long (4 byte) mode\n"
1837 " u change to doubleword (8 byte) mode\n"
1838 " m addr change current addr\n"
1839 " n toggle no-read flag\n"
1840 " r toggle byte reverse flag\n"
1841 " < count back up count bytes\n"
1842 " > count skip forward count bytes\n"
1843 " x exit this mode\n"
1849 int cmd
, inc
, i
, nslash
;
1851 unsigned char val
[16];
1853 scanhex((void *)&adrs
);
1856 printf(memex_help_string
);
1862 while ((cmd
= skipbl()) != '\n') {
1864 case 'b': size
= 1; break;
1865 case 'w': size
= 2; break;
1866 case 'l': size
= 4; break;
1867 case 'd': size
= 8; break;
1868 case 'r': brev
= !brev
; break;
1869 case 'n': mnoread
= 1; break;
1870 case '.': mnoread
= 0; break;
1879 n
= mread(adrs
, val
, size
);
1880 printf(REG
"%c", adrs
, brev
? 'r': ' ');
1885 for (i
= 0; i
< n
; ++i
)
1886 printf("%.2x", val
[i
]);
1887 for (; i
< size
; ++i
)
1888 printf("%s", fault_chars
[fault_type
]);
1895 for (i
= 0; i
< size
; ++i
)
1896 val
[i
] = n
>> (i
* 8);
1899 mwrite(adrs
, val
, size
);
1912 else if( n
== '\'' )
1914 for (i
= 0; i
< size
; ++i
)
1915 val
[i
] = n
>> (i
* 8);
1918 mwrite(adrs
, val
, size
);
1955 adrs
-= 1 << nslash
;
1959 adrs
+= 1 << nslash
;
1963 adrs
+= 1 << -nslash
;
1967 adrs
-= 1 << -nslash
;
1970 scanhex((void *)&adrs
);
1989 printf(memex_subcmd_help_string
);
2004 case 'n': c
= '\n'; break;
2005 case 'r': c
= '\r'; break;
2006 case 'b': c
= '\b'; break;
2007 case 't': c
= '\t'; break;
2012 static void xmon_rawdump (unsigned long adrs
, long ndump
)
2015 unsigned char temp
[16];
2017 for (n
= ndump
; n
> 0;) {
2019 nr
= mread(adrs
, temp
, r
);
2021 for (m
= 0; m
< r
; ++m
) {
2023 printf("%.2x", temp
[m
]);
2025 printf("%s", fault_chars
[fault_type
]);
2035 static void dump_one_paca(int cpu
)
2037 struct paca_struct
*p
;
2039 if (setjmp(bus_error_jmp
) != 0) {
2040 printf("*** Error dumping paca for cpu 0x%x!\n", cpu
);
2044 catch_memory_errors
= 1;
2049 printf("paca for cpu 0x%x @ %p:\n", cpu
, p
);
2051 printf(" %-*s = %s\n", 16, "possible", cpu_possible(cpu
) ? "yes" : "no");
2052 printf(" %-*s = %s\n", 16, "present", cpu_present(cpu
) ? "yes" : "no");
2053 printf(" %-*s = %s\n", 16, "online", cpu_online(cpu
) ? "yes" : "no");
2055 #define DUMP(paca, name, format) \
2056 printf(" %-*s = %#-*"format"\t(0x%lx)\n", 16, #name, 18, paca->name, \
2057 offsetof(struct paca_struct, name));
2059 DUMP(p
, lock_token
, "x");
2060 DUMP(p
, paca_index
, "x");
2061 DUMP(p
, kernel_toc
, "lx");
2062 DUMP(p
, kernelbase
, "lx");
2063 DUMP(p
, kernel_msr
, "lx");
2064 DUMP(p
, emergency_sp
, "p");
2065 #ifdef CONFIG_PPC_BOOK3S_64
2066 DUMP(p
, mc_emergency_sp
, "p");
2067 DUMP(p
, in_mce
, "x");
2069 DUMP(p
, data_offset
, "lx");
2070 DUMP(p
, hw_cpu_id
, "x");
2071 DUMP(p
, cpu_start
, "x");
2072 DUMP(p
, kexec_state
, "x");
2073 DUMP(p
, __current
, "p");
2074 DUMP(p
, kstack
, "lx");
2075 DUMP(p
, stab_rr
, "lx");
2076 DUMP(p
, saved_r1
, "lx");
2077 DUMP(p
, trap_save
, "x");
2078 DUMP(p
, soft_enabled
, "x");
2079 DUMP(p
, irq_happened
, "x");
2080 DUMP(p
, io_sync
, "x");
2081 DUMP(p
, irq_work_pending
, "x");
2082 DUMP(p
, nap_state_lost
, "x");
2086 catch_memory_errors
= 0;
2090 static void dump_all_pacas(void)
2094 if (num_possible_cpus() == 0) {
2095 printf("No possible cpus, use 'dp #' to dump individual cpus\n");
2099 for_each_possible_cpu(cpu
)
2103 static void dump_pacas(void)
2114 termch
= c
; /* Put c back, it wasn't 'a' */
2119 dump_one_paca(xmon_owner
);
2123 #define isxdigit(c) (('0' <= (c) && (c) <= '9') \
2124 || ('a' <= (c) && (c) <= 'f') \
2125 || ('A' <= (c) && (c) <= 'F'))
2140 if ((isxdigit(c
) && c
!= 'f' && c
!= 'd') || c
== '\n')
2142 scanhex((void *)&adrs
);
2149 else if (nidump
> MAX_DUMP
)
2151 adrs
+= ppc_inst_dump(adrs
, nidump
, 1);
2153 } else if (c
== 'l') {
2155 } else if (c
== 'r') {
2159 xmon_rawdump(adrs
, ndump
);
2166 else if (ndump
> MAX_DUMP
)
2168 prdump(adrs
, ndump
);
2175 prdump(unsigned long adrs
, long ndump
)
2177 long n
, m
, c
, r
, nr
;
2178 unsigned char temp
[16];
2180 for (n
= ndump
; n
> 0;) {
2184 nr
= mread(adrs
, temp
, r
);
2186 for (m
= 0; m
< r
; ++m
) {
2187 if ((m
& (sizeof(long) - 1)) == 0 && m
> 0)
2190 printf("%.2x", temp
[m
]);
2192 printf("%s", fault_chars
[fault_type
]);
2194 for (; m
< 16; ++m
) {
2195 if ((m
& (sizeof(long) - 1)) == 0)
2200 for (m
= 0; m
< r
; ++m
) {
2203 putchar(' ' <= c
&& c
<= '~'? c
: '.');
2216 typedef int (*instruction_dump_func
)(unsigned long inst
, unsigned long addr
);
2219 generic_inst_dump(unsigned long adr
, long count
, int praddr
,
2220 instruction_dump_func dump_func
)
2223 unsigned long first_adr
;
2224 unsigned long inst
, last_inst
= 0;
2225 unsigned char val
[4];
2228 for (first_adr
= adr
; count
> 0; --count
, adr
+= 4) {
2229 nr
= mread(adr
, val
, 4);
2232 const char *x
= fault_chars
[fault_type
];
2233 printf(REG
" %s%s%s%s\n", adr
, x
, x
, x
, x
);
2237 inst
= GETWORD(val
);
2238 if (adr
> first_adr
&& inst
== last_inst
) {
2248 printf(REG
" %.8x", adr
, inst
);
2250 dump_func(inst
, adr
);
2253 return adr
- first_adr
;
2257 ppc_inst_dump(unsigned long adr
, long count
, int praddr
)
2259 return generic_inst_dump(adr
, count
, praddr
, print_insn_powerpc
);
2263 print_address(unsigned long addr
)
2265 xmon_print_symbol(addr
, "\t# ", "");
2271 struct kmsg_dumper dumper
= { .active
= 1 };
2272 unsigned char buf
[128];
2275 if (setjmp(bus_error_jmp
) != 0) {
2276 printf("Error dumping printk buffer!\n");
2280 catch_memory_errors
= 1;
2283 kmsg_dump_rewind_nolock(&dumper
);
2284 while (kmsg_dump_get_line_nolock(&dumper
, false, buf
, sizeof(buf
), &len
)) {
2290 /* wait a little while to see if we get a machine check */
2292 catch_memory_errors
= 0;
2296 * Memory operations - move, set, print differences
2298 static unsigned long mdest
; /* destination address */
2299 static unsigned long msrc
; /* source address */
2300 static unsigned long mval
; /* byte value to set memory to */
2301 static unsigned long mcount
; /* # bytes to affect */
2302 static unsigned long mdiffs
; /* max # differences to print */
2307 scanhex((void *)&mdest
);
2308 if( termch
!= '\n' )
2310 scanhex((void *)(cmd
== 's'? &mval
: &msrc
));
2311 if( termch
!= '\n' )
2313 scanhex((void *)&mcount
);
2316 memmove((void *)mdest
, (void *)msrc
, mcount
);
2319 memset((void *)mdest
, mval
, mcount
);
2322 if( termch
!= '\n' )
2324 scanhex((void *)&mdiffs
);
2325 memdiffs((unsigned char *)mdest
, (unsigned char *)msrc
, mcount
, mdiffs
);
2331 memdiffs(unsigned char *p1
, unsigned char *p2
, unsigned nb
, unsigned maxpr
)
2336 for( n
= nb
; n
> 0; --n
)
2337 if( *p1
++ != *p2
++ )
2338 if( ++prt
<= maxpr
)
2339 printf("%.16x %.2x # %.16x %.2x\n", p1
- 1,
2340 p1
[-1], p2
- 1, p2
[-1]);
2342 printf("Total of %d differences\n", prt
);
2345 static unsigned mend
;
2346 static unsigned mask
;
2352 unsigned char val
[4];
2355 scanhex((void *)&mdest
);
2356 if (termch
!= '\n') {
2358 scanhex((void *)&mend
);
2359 if (termch
!= '\n') {
2361 scanhex((void *)&mval
);
2363 if (termch
!= '\n') termch
= 0;
2364 scanhex((void *)&mask
);
2368 for (a
= mdest
; a
< mend
; a
+= 4) {
2369 if (mread(a
, val
, 4) == 4
2370 && ((GETWORD(val
) ^ mval
) & mask
) == 0) {
2371 printf("%.16x: %.16x\n", a
, GETWORD(val
));
2378 static unsigned long mskip
= 0x1000;
2379 static unsigned long mlim
= 0xffffffff;
2389 if (termch
!= '\n') termch
= 0;
2391 if (termch
!= '\n') termch
= 0;
2394 for (a
= mdest
; a
< mlim
; a
+= mskip
) {
2395 ok
= mread(a
, &v
, 1);
2397 printf("%.8x .. ", a
);
2398 } else if (!ok
&& ook
)
2399 printf("%.8x\n", a
- mskip
);
2405 printf("%.8x\n", a
- mskip
);
2408 static void proccall(void)
2410 unsigned long args
[8];
2413 typedef unsigned long (*callfunc_t
)(unsigned long, unsigned long,
2414 unsigned long, unsigned long, unsigned long,
2415 unsigned long, unsigned long, unsigned long);
2418 if (!scanhex(&adrs
))
2422 for (i
= 0; i
< 8; ++i
)
2424 for (i
= 0; i
< 8; ++i
) {
2425 if (!scanhex(&args
[i
]) || termch
== '\n')
2429 func
= (callfunc_t
) adrs
;
2431 if (setjmp(bus_error_jmp
) == 0) {
2432 catch_memory_errors
= 1;
2434 ret
= func(args
[0], args
[1], args
[2], args
[3],
2435 args
[4], args
[5], args
[6], args
[7]);
2437 printf("return value is 0x%lx\n", ret
);
2439 printf("*** %x exception occurred\n", fault_except
);
2441 catch_memory_errors
= 0;
2444 /* Input scanning routines */
2455 while( c
== ' ' || c
== '\t' )
2461 static char *regnames
[N_PTREGS
] = {
2462 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
2463 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
2464 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
2465 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
2466 "pc", "msr", "or3", "ctr", "lr", "xer", "ccr",
2472 "trap", "dar", "dsisr", "res"
2476 scanhex(unsigned long *vp
)
2483 /* parse register name */
2487 for (i
= 0; i
< sizeof(regname
) - 1; ++i
) {
2496 for (i
= 0; i
< N_PTREGS
; ++i
) {
2497 if (strcmp(regnames
[i
], regname
) == 0) {
2498 if (xmon_regs
== NULL
) {
2499 printf("regs not available\n");
2502 *vp
= ((unsigned long *)xmon_regs
)[i
];
2506 printf("invalid register name '%%%s'\n", regname
);
2510 /* skip leading "0x" if any */
2524 } else if (c
== '$') {
2526 for (i
=0; i
<63; i
++) {
2536 if (setjmp(bus_error_jmp
) == 0) {
2537 catch_memory_errors
= 1;
2539 *vp
= kallsyms_lookup_name(tmpstr
);
2542 catch_memory_errors
= 0;
2544 printf("unknown symbol '%s'\n", tmpstr
);
2577 static int hexdigit(int c
)
2579 if( '0' <= c
&& c
<= '9' )
2581 if( 'A' <= c
&& c
<= 'F' )
2582 return c
- ('A' - 10);
2583 if( 'a' <= c
&& c
<= 'f' )
2584 return c
- ('a' - 10);
2589 getstring(char *s
, int size
)
2600 } while( c
!= ' ' && c
!= '\t' && c
!= '\n' );
2605 static char line
[256];
2606 static char *lineptr
;
2617 if (lineptr
== NULL
|| *lineptr
== 0) {
2618 if (xmon_gets(line
, sizeof(line
)) == NULL
) {
2628 take_input(char *str
)
2637 int type
= inchar();
2639 static char tmp
[64];
2644 xmon_print_symbol(addr
, ": ", "\n");
2649 if (setjmp(bus_error_jmp
) == 0) {
2650 catch_memory_errors
= 1;
2652 addr
= kallsyms_lookup_name(tmp
);
2654 printf("%s: %lx\n", tmp
, addr
);
2656 printf("Symbol '%s' not found.\n", tmp
);
2659 catch_memory_errors
= 0;
2666 /* Print an address in numeric and symbolic form (if possible) */
2667 static void xmon_print_symbol(unsigned long address
, const char *mid
,
2671 const char *name
= NULL
;
2672 unsigned long offset
, size
;
2674 printf(REG
, address
);
2675 if (setjmp(bus_error_jmp
) == 0) {
2676 catch_memory_errors
= 1;
2678 name
= kallsyms_lookup(address
, &size
, &offset
, &modname
,
2681 /* wait a little while to see if we get a machine check */
2685 catch_memory_errors
= 0;
2688 printf("%s%s+%#lx/%#lx", mid
, name
, offset
, size
);
2690 printf(" [%s]", modname
);
2692 printf("%s", after
);
2695 #ifdef CONFIG_PPC_BOOK3S_64
2696 void dump_segments(void)
2699 unsigned long esid
,vsid
,valid
;
2702 printf("SLB contents of cpu 0x%x\n", smp_processor_id());
2704 for (i
= 0; i
< mmu_slb_size
; i
++) {
2705 asm volatile("slbmfee %0,%1" : "=r" (esid
) : "r" (i
));
2706 asm volatile("slbmfev %0,%1" : "=r" (vsid
) : "r" (i
));
2707 valid
= (esid
& SLB_ESID_V
);
2708 if (valid
| esid
| vsid
) {
2709 printf("%02d %016lx %016lx", i
, esid
, vsid
);
2711 llp
= vsid
& SLB_VSID_LLP
;
2712 if (vsid
& SLB_VSID_B_1T
) {
2713 printf(" 1T ESID=%9lx VSID=%13lx LLP:%3lx \n",
2715 (vsid
& ~SLB_VSID_B
) >> SLB_VSID_SHIFT_1T
,
2718 printf(" 256M ESID=%9lx VSID=%13lx LLP:%3lx \n",
2720 (vsid
& ~SLB_VSID_B
) >> SLB_VSID_SHIFT
,
2730 #ifdef CONFIG_PPC_STD_MMU_32
2731 void dump_segments(void)
2736 for (i
= 0; i
< 16; ++i
)
2737 printf(" %x", mfsrin(i
));
2743 static void dump_tlb_44x(void)
2747 for (i
= 0; i
< PPC44x_TLB_SIZE
; i
++) {
2748 unsigned long w0
,w1
,w2
;
2749 asm volatile("tlbre %0,%1,0" : "=r" (w0
) : "r" (i
));
2750 asm volatile("tlbre %0,%1,1" : "=r" (w1
) : "r" (i
));
2751 asm volatile("tlbre %0,%1,2" : "=r" (w2
) : "r" (i
));
2752 printf("[%02x] %08x %08x %08x ", i
, w0
, w1
, w2
);
2753 if (w0
& PPC44x_TLB_VALID
) {
2754 printf("V %08x -> %01x%08x %c%c%c%c%c",
2755 w0
& PPC44x_TLB_EPN_MASK
,
2756 w1
& PPC44x_TLB_ERPN_MASK
,
2757 w1
& PPC44x_TLB_RPN_MASK
,
2758 (w2
& PPC44x_TLB_W
) ? 'W' : 'w',
2759 (w2
& PPC44x_TLB_I
) ? 'I' : 'i',
2760 (w2
& PPC44x_TLB_M
) ? 'M' : 'm',
2761 (w2
& PPC44x_TLB_G
) ? 'G' : 'g',
2762 (w2
& PPC44x_TLB_E
) ? 'E' : 'e');
2767 #endif /* CONFIG_44x */
2769 #ifdef CONFIG_PPC_BOOK3E
2770 static void dump_tlb_book3e(void)
2772 u32 mmucfg
, pidmask
, lpidmask
;
2774 int i
, tlb
, ntlbs
, pidsz
, lpidsz
, rasz
, lrat
= 0;
2776 static const char *pgsz_names
[] = {
2811 /* Gather some infos about the MMU */
2812 mmucfg
= mfspr(SPRN_MMUCFG
);
2813 mmu_version
= (mmucfg
& 3) + 1;
2814 ntlbs
= ((mmucfg
>> 2) & 3) + 1;
2815 pidsz
= ((mmucfg
>> 6) & 0x1f) + 1;
2816 lpidsz
= (mmucfg
>> 24) & 0xf;
2817 rasz
= (mmucfg
>> 16) & 0x7f;
2818 if ((mmu_version
> 1) && (mmucfg
& 0x10000))
2820 printf("Book3E MMU MAV=%d.0,%d TLBs,%d-bit PID,%d-bit LPID,%d-bit RA\n",
2821 mmu_version
, ntlbs
, pidsz
, lpidsz
, rasz
);
2822 pidmask
= (1ul << pidsz
) - 1;
2823 lpidmask
= (1ul << lpidsz
) - 1;
2824 ramask
= (1ull << rasz
) - 1;
2826 for (tlb
= 0; tlb
< ntlbs
; tlb
++) {
2828 int nent
, assoc
, new_cc
= 1;
2829 printf("TLB %d:\n------\n", tlb
);
2832 tlbcfg
= mfspr(SPRN_TLB0CFG
);
2835 tlbcfg
= mfspr(SPRN_TLB1CFG
);
2838 tlbcfg
= mfspr(SPRN_TLB2CFG
);
2841 tlbcfg
= mfspr(SPRN_TLB3CFG
);
2844 printf("Unsupported TLB number !\n");
2847 nent
= tlbcfg
& 0xfff;
2848 assoc
= (tlbcfg
>> 24) & 0xff;
2849 for (i
= 0; i
< nent
; i
++) {
2850 u32 mas0
= MAS0_TLBSEL(tlb
);
2851 u32 mas1
= MAS1_TSIZE(BOOK3E_PAGESZ_4K
);
2854 int esel
= i
, cc
= i
;
2862 mas0
|= MAS0_ESEL(esel
);
2863 mtspr(SPRN_MAS0
, mas0
);
2864 mtspr(SPRN_MAS1
, mas1
);
2865 mtspr(SPRN_MAS2
, mas2
);
2866 asm volatile("tlbre 0,0,0" : : : "memory");
2867 mas1
= mfspr(SPRN_MAS1
);
2868 mas2
= mfspr(SPRN_MAS2
);
2869 mas7_mas3
= mfspr(SPRN_MAS7_MAS3
);
2870 if (assoc
&& (i
% assoc
) == 0)
2872 if (!(mas1
& MAS1_VALID
))
2875 printf("%04x- ", i
);
2877 printf("%04x-%c", cc
, 'A' + esel
);
2879 printf(" |%c", 'A' + esel
);
2881 printf(" %016llx %04x %s %c%c AS%c",
2883 (mas1
>> 16) & 0x3fff,
2884 pgsz_names
[(mas1
>> 7) & 0x1f],
2885 mas1
& MAS1_IND
? 'I' : ' ',
2886 mas1
& MAS1_IPROT
? 'P' : ' ',
2887 mas1
& MAS1_TS
? '1' : '0');
2888 printf(" %c%c%c%c%c%c%c",
2889 mas2
& MAS2_X0
? 'a' : ' ',
2890 mas2
& MAS2_X1
? 'v' : ' ',
2891 mas2
& MAS2_W
? 'w' : ' ',
2892 mas2
& MAS2_I
? 'i' : ' ',
2893 mas2
& MAS2_M
? 'm' : ' ',
2894 mas2
& MAS2_G
? 'g' : ' ',
2895 mas2
& MAS2_E
? 'e' : ' ');
2896 printf(" %016llx", mas7_mas3
& ramask
& ~0x7ffull
);
2897 if (mas1
& MAS1_IND
)
2899 pgsz_names
[(mas7_mas3
>> 1) & 0x1f]);
2901 printf(" U%c%c%c S%c%c%c\n",
2902 mas7_mas3
& MAS3_UX
? 'x' : ' ',
2903 mas7_mas3
& MAS3_UW
? 'w' : ' ',
2904 mas7_mas3
& MAS3_UR
? 'r' : ' ',
2905 mas7_mas3
& MAS3_SX
? 'x' : ' ',
2906 mas7_mas3
& MAS3_SW
? 'w' : ' ',
2907 mas7_mas3
& MAS3_SR
? 'r' : ' ');
2911 #endif /* CONFIG_PPC_BOOK3E */
2913 static void xmon_init(int enable
)
2917 __debugger_ipi
= xmon_ipi
;
2918 __debugger_bpt
= xmon_bpt
;
2919 __debugger_sstep
= xmon_sstep
;
2920 __debugger_iabr_match
= xmon_iabr_match
;
2921 __debugger_break_match
= xmon_break_match
;
2922 __debugger_fault_handler
= xmon_fault_handler
;
2925 __debugger_ipi
= NULL
;
2926 __debugger_bpt
= NULL
;
2927 __debugger_sstep
= NULL
;
2928 __debugger_iabr_match
= NULL
;
2929 __debugger_break_match
= NULL
;
2930 __debugger_fault_handler
= NULL
;
2934 #ifdef CONFIG_MAGIC_SYSRQ
2935 static void sysrq_handle_xmon(int key
)
2937 /* ensure xmon is enabled */
2939 debugger(get_irq_regs());
2942 static struct sysrq_key_op sysrq_xmon_op
= {
2943 .handler
= sysrq_handle_xmon
,
2944 .help_msg
= "xmon(x)",
2945 .action_msg
= "Entering xmon",
2948 static int __init
setup_xmon_sysrq(void)
2950 register_sysrq_key('x', &sysrq_xmon_op
);
2953 __initcall(setup_xmon_sysrq
);
2954 #endif /* CONFIG_MAGIC_SYSRQ */
2956 static int __initdata xmon_early
, xmon_off
;
2958 static int __init
early_parse_xmon(char *p
)
2960 if (!p
|| strncmp(p
, "early", 5) == 0) {
2961 /* just "xmon" is equivalent to "xmon=early" */
2964 } else if (strncmp(p
, "on", 2) == 0)
2966 else if (strncmp(p
, "off", 3) == 0)
2968 else if (strncmp(p
, "nobt", 4) == 0)
2969 xmon_no_auto_backtrace
= 1;
2975 early_param("xmon", early_parse_xmon
);
2977 void __init
xmon_setup(void)
2979 #ifdef CONFIG_XMON_DEFAULT
2987 #ifdef CONFIG_SPU_BASE
2991 u64 saved_mfc_sr1_RW
;
2992 u32 saved_spu_runcntl_RW
;
2993 unsigned long dump_addr
;
2997 #define XMON_NUM_SPUS 16 /* Enough for current hardware */
2999 static struct spu_info spu_info
[XMON_NUM_SPUS
];
3001 void xmon_register_spus(struct list_head
*list
)
3005 list_for_each_entry(spu
, list
, full_list
) {
3006 if (spu
->number
>= XMON_NUM_SPUS
) {
3011 spu_info
[spu
->number
].spu
= spu
;
3012 spu_info
[spu
->number
].stopped_ok
= 0;
3013 spu_info
[spu
->number
].dump_addr
= (unsigned long)
3014 spu_info
[spu
->number
].spu
->local_store
;
3018 static void stop_spus(void)
3024 for (i
= 0; i
< XMON_NUM_SPUS
; i
++) {
3025 if (!spu_info
[i
].spu
)
3028 if (setjmp(bus_error_jmp
) == 0) {
3029 catch_memory_errors
= 1;
3032 spu
= spu_info
[i
].spu
;
3034 spu_info
[i
].saved_spu_runcntl_RW
=
3035 in_be32(&spu
->problem
->spu_runcntl_RW
);
3037 tmp
= spu_mfc_sr1_get(spu
);
3038 spu_info
[i
].saved_mfc_sr1_RW
= tmp
;
3040 tmp
&= ~MFC_STATE1_MASTER_RUN_CONTROL_MASK
;
3041 spu_mfc_sr1_set(spu
, tmp
);
3046 spu_info
[i
].stopped_ok
= 1;
3048 printf("Stopped spu %.2d (was %s)\n", i
,
3049 spu_info
[i
].saved_spu_runcntl_RW
?
3050 "running" : "stopped");
3052 catch_memory_errors
= 0;
3053 printf("*** Error stopping spu %.2d\n", i
);
3055 catch_memory_errors
= 0;
3059 static void restart_spus(void)
3064 for (i
= 0; i
< XMON_NUM_SPUS
; i
++) {
3065 if (!spu_info
[i
].spu
)
3068 if (!spu_info
[i
].stopped_ok
) {
3069 printf("*** Error, spu %d was not successfully stopped"
3070 ", not restarting\n", i
);
3074 if (setjmp(bus_error_jmp
) == 0) {
3075 catch_memory_errors
= 1;
3078 spu
= spu_info
[i
].spu
;
3079 spu_mfc_sr1_set(spu
, spu_info
[i
].saved_mfc_sr1_RW
);
3080 out_be32(&spu
->problem
->spu_runcntl_RW
,
3081 spu_info
[i
].saved_spu_runcntl_RW
);
3086 printf("Restarted spu %.2d\n", i
);
3088 catch_memory_errors
= 0;
3089 printf("*** Error restarting spu %.2d\n", i
);
3091 catch_memory_errors
= 0;
3095 #define DUMP_WIDTH 23
3096 #define DUMP_VALUE(format, field, value) \
3098 if (setjmp(bus_error_jmp) == 0) { \
3099 catch_memory_errors = 1; \
3101 printf(" %-*s = "format"\n", DUMP_WIDTH, \
3106 catch_memory_errors = 0; \
3107 printf(" %-*s = *** Error reading field.\n", \
3108 DUMP_WIDTH, #field); \
3110 catch_memory_errors = 0; \
3113 #define DUMP_FIELD(obj, format, field) \
3114 DUMP_VALUE(format, field, obj->field)
3116 static void dump_spu_fields(struct spu
*spu
)
3118 printf("Dumping spu fields at address %p:\n", spu
);
3120 DUMP_FIELD(spu
, "0x%x", number
);
3121 DUMP_FIELD(spu
, "%s", name
);
3122 DUMP_FIELD(spu
, "0x%lx", local_store_phys
);
3123 DUMP_FIELD(spu
, "0x%p", local_store
);
3124 DUMP_FIELD(spu
, "0x%lx", ls_size
);
3125 DUMP_FIELD(spu
, "0x%x", node
);
3126 DUMP_FIELD(spu
, "0x%lx", flags
);
3127 DUMP_FIELD(spu
, "%d", class_0_pending
);
3128 DUMP_FIELD(spu
, "0x%lx", class_0_dar
);
3129 DUMP_FIELD(spu
, "0x%lx", class_1_dar
);
3130 DUMP_FIELD(spu
, "0x%lx", class_1_dsisr
);
3131 DUMP_FIELD(spu
, "0x%lx", irqs
[0]);
3132 DUMP_FIELD(spu
, "0x%lx", irqs
[1]);
3133 DUMP_FIELD(spu
, "0x%lx", irqs
[2]);
3134 DUMP_FIELD(spu
, "0x%x", slb_replace
);
3135 DUMP_FIELD(spu
, "%d", pid
);
3136 DUMP_FIELD(spu
, "0x%p", mm
);
3137 DUMP_FIELD(spu
, "0x%p", ctx
);
3138 DUMP_FIELD(spu
, "0x%p", rq
);
3139 DUMP_FIELD(spu
, "0x%p", timestamp
);
3140 DUMP_FIELD(spu
, "0x%lx", problem_phys
);
3141 DUMP_FIELD(spu
, "0x%p", problem
);
3142 DUMP_VALUE("0x%x", problem
->spu_runcntl_RW
,
3143 in_be32(&spu
->problem
->spu_runcntl_RW
));
3144 DUMP_VALUE("0x%x", problem
->spu_status_R
,
3145 in_be32(&spu
->problem
->spu_status_R
));
3146 DUMP_VALUE("0x%x", problem
->spu_npc_RW
,
3147 in_be32(&spu
->problem
->spu_npc_RW
));
3148 DUMP_FIELD(spu
, "0x%p", priv2
);
3149 DUMP_FIELD(spu
, "0x%p", pdata
);
3153 spu_inst_dump(unsigned long adr
, long count
, int praddr
)
3155 return generic_inst_dump(adr
, count
, praddr
, print_insn_spu
);
3158 static void dump_spu_ls(unsigned long num
, int subcmd
)
3160 unsigned long offset
, addr
, ls_addr
;
3162 if (setjmp(bus_error_jmp
) == 0) {
3163 catch_memory_errors
= 1;
3165 ls_addr
= (unsigned long)spu_info
[num
].spu
->local_store
;
3169 catch_memory_errors
= 0;
3170 printf("*** Error: accessing spu info for spu %d\n", num
);
3173 catch_memory_errors
= 0;
3175 if (scanhex(&offset
))
3176 addr
= ls_addr
+ offset
;
3178 addr
= spu_info
[num
].dump_addr
;
3180 if (addr
>= ls_addr
+ LS_SIZE
) {
3181 printf("*** Error: address outside of local store\n");
3187 addr
+= spu_inst_dump(addr
, 16, 1);
3197 spu_info
[num
].dump_addr
= addr
;
3200 static int do_spu_cmd(void)
3202 static unsigned long num
= 0;
3203 int cmd
, subcmd
= 0;
3215 if (isxdigit(subcmd
) || subcmd
== '\n')
3219 if (num
>= XMON_NUM_SPUS
|| !spu_info
[num
].spu
) {
3220 printf("*** Error: invalid spu number\n");
3226 dump_spu_fields(spu_info
[num
].spu
);
3229 dump_spu_ls(num
, subcmd
);
3240 #else /* ! CONFIG_SPU_BASE */
3241 static int do_spu_cmd(void)