2 * Routines providing a simple monitor for use on the PowerMac.
4 * Copyright (C) 1996-2005 Paul Mackerras.
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
11 #include <linux/config.h>
12 #include <linux/errno.h>
13 #include <linux/sched.h>
14 #include <linux/smp.h>
16 #include <linux/reboot.h>
17 #include <linux/delay.h>
18 #include <linux/kallsyms.h>
19 #include <linux/cpumask.h>
20 #include <linux/module.h>
21 #include <linux/sysrq.h>
22 #include <linux/interrupt.h>
24 #include <asm/ptrace.h>
25 #include <asm/string.h>
27 #include <asm/machdep.h>
29 #ifdef CONFIG_PMAC_BACKLIGHT
30 #include <asm/backlight.h>
32 #include <asm/processor.h>
33 #include <asm/pgtable.h>
35 #include <asm/mmu_context.h>
36 #include <asm/cputable.h>
38 #include <asm/sstep.h>
42 #include <asm/hvcall.h>
48 #define scanhex xmon_scanhex
49 #define skipbl xmon_skipbl
52 cpumask_t cpus_in_xmon
= CPU_MASK_NONE
;
53 static unsigned long xmon_taken
= 1;
54 static int xmon_owner
;
56 #endif /* CONFIG_SMP */
58 static unsigned long in_xmon
= 0;
60 static unsigned long adrs
;
62 #define MAX_DUMP (128 * 1024)
63 static unsigned long ndump
= 64;
64 static unsigned long nidump
= 16;
65 static unsigned long ncsum
= 4096;
67 static char tmpstr
[128];
69 #define JMP_BUF_LEN 23
70 static long bus_error_jmp
[JMP_BUF_LEN
];
71 static int catch_memory_errors
;
72 static long *xmon_fault_jmp
[NR_CPUS
];
73 #define setjmp xmon_setjmp
74 #define longjmp xmon_longjmp
76 /* Breakpoint stuff */
78 unsigned long address
;
79 unsigned int instr
[2];
85 /* Bits in bpt.enabled */
86 #define BP_IABR_TE 1 /* IABR translation enabled */
92 static struct bpt bpts
[NBPTS
];
93 static struct bpt dabr
;
94 static struct bpt
*iabr
;
95 static unsigned bpinstr
= 0x7fe00008; /* trap */
97 #define BP_NUM(bp) ((bp) - bpts + 1)
100 static int cmds(struct pt_regs
*);
101 static int mread(unsigned long, void *, int);
102 static int mwrite(unsigned long, void *, int);
103 static int handle_fault(struct pt_regs
*);
104 static void byterev(unsigned char *, int);
105 static void memex(void);
106 static int bsesc(void);
107 static void dump(void);
108 static void prdump(unsigned long, long);
109 static int ppc_inst_dump(unsigned long, long, int);
110 void print_address(unsigned long);
111 static void backtrace(struct pt_regs
*);
112 static void excprint(struct pt_regs
*);
113 static void prregs(struct pt_regs
*);
114 static void memops(int);
115 static void memlocate(void);
116 static void memzcan(void);
117 static void memdiffs(unsigned char *, unsigned char *, unsigned, unsigned);
119 int scanhex(unsigned long *valp
);
120 static void scannl(void);
121 static int hexdigit(int);
122 void getstring(char *, int);
123 static void flush_input(void);
124 static int inchar(void);
125 static void take_input(char *);
126 static unsigned long read_spr(int);
127 static void write_spr(int, unsigned long);
128 static void super_regs(void);
129 static void remove_bpts(void);
130 static void insert_bpts(void);
131 static void remove_cpu_bpts(void);
132 static void insert_cpu_bpts(void);
133 static struct bpt
*at_breakpoint(unsigned long pc
);
134 static struct bpt
*in_breakpoint_table(unsigned long pc
, unsigned long *offp
);
135 static int do_step(struct pt_regs
*);
136 static void bpt_cmds(void);
137 static void cacheflush(void);
138 static int cpu_cmd(void);
139 static void csum(void);
140 static void bootcmds(void);
141 static void proccall(void);
142 void dump_segments(void);
143 static void symbol_lookup(void);
144 static void xmon_print_symbol(unsigned long address
, const char *mid
,
146 static const char *getvecname(unsigned long vec
);
148 extern int print_insn_powerpc(unsigned long, unsigned long, int);
150 extern void xmon_enter(void);
151 extern void xmon_leave(void);
153 extern long setjmp(long *);
154 extern void longjmp(long *, long);
155 extern void xmon_save_regs(struct pt_regs
*);
159 #define REGS_PER_LINE 4
160 #define LAST_VOLATILE 13
163 #define REGS_PER_LINE 8
164 #define LAST_VOLATILE 12
167 #define GETWORD(v) (((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
169 #define isxdigit(c) (('0' <= (c) && (c) <= '9') \
170 || ('a' <= (c) && (c) <= 'f') \
171 || ('A' <= (c) && (c) <= 'F'))
172 #define isalnum(c) (('0' <= (c) && (c) <= '9') \
173 || ('a' <= (c) && (c) <= 'z') \
174 || ('A' <= (c) && (c) <= 'Z'))
175 #define isspace(c) (c == ' ' || c == '\t' || c == 10 || c == 13 || c == 0)
177 static char *help_string
= "\
179 b show breakpoints\n\
180 bd set data breakpoint\n\
181 bi set instruction breakpoint\n\
182 bc clear breakpoint\n"
185 c print cpus stopped in xmon\n\
186 c# try to switch to cpu number h (in hex)\n"
191 di dump instructions\n\
192 df dump float values\n\
193 dd dump double values\n\
194 dr dump stream of raw bytes\n\
195 e print exception information\n\
197 la lookup symbol+offset of specified address\n\
198 ls lookup address of specified symbol\n\
199 m examine/change memory\n\
200 mm move a block of memory\n\
201 ms set a block of memory\n\
202 md compare two blocks of memory\n\
203 ml locate a block of memory\n\
204 mz zero a block of memory\n\
205 mi show information about memory allocation\n\
206 p call a procedure\n\
209 S print special registers\n\
211 x exit monitor and recover\n\
212 X exit monitor and dont recover\n"
214 " u dump segment table or SLB\n"
216 #ifdef CONFIG_PPC_STD_MMU_32
217 " u dump segment registers\n"
224 static struct pt_regs
*xmon_regs
;
226 static inline void sync(void)
228 asm volatile("sync; isync");
231 static inline void store_inst(void *p
)
233 asm volatile ("dcbst 0,%0; sync; icbi 0,%0; isync" : : "r" (p
));
236 static inline void cflush(void *p
)
238 asm volatile ("dcbf 0,%0; icbi 0,%0" : : "r" (p
));
241 static inline void cinval(void *p
)
243 asm volatile ("dcbi 0,%0; icbi 0,%0" : : "r" (p
));
247 * Disable surveillance (the service processor watchdog function)
248 * while we are in xmon.
249 * XXX we should re-enable it when we leave. :)
251 #define SURVEILLANCE_TOKEN 9000
253 static inline void disable_surveillance(void)
255 #ifdef CONFIG_PPC_PSERIES
256 /* Since this can't be a module, args should end up below 4GB. */
257 static struct rtas_args args
;
260 * At this point we have got all the cpus we can into
261 * xmon, so there is hopefully no other cpu calling RTAS
262 * at the moment, even though we don't take rtas.lock.
263 * If we did try to take rtas.lock there would be a
264 * real possibility of deadlock.
266 args
.token
= rtas_token("set-indicator");
267 if (args
.token
== RTAS_UNKNOWN_SERVICE
)
271 args
.rets
= &args
.args
[3];
272 args
.args
[0] = SURVEILLANCE_TOKEN
;
275 enter_rtas(__pa(&args
));
276 #endif /* CONFIG_PPC_PSERIES */
280 static int xmon_speaker
;
282 static void get_output_lock(void)
284 int me
= smp_processor_id() + 0x100;
285 int last_speaker
= 0, prev
;
288 if (xmon_speaker
== me
)
291 if (xmon_speaker
== 0) {
292 last_speaker
= cmpxchg(&xmon_speaker
, 0, me
);
293 if (last_speaker
== 0)
297 while (xmon_speaker
== last_speaker
) {
300 /* hostile takeover */
301 prev
= cmpxchg(&xmon_speaker
, last_speaker
, me
);
302 if (prev
== last_speaker
)
309 static void release_output_lock(void)
315 static int xmon_core(struct pt_regs
*regs
, int fromipi
)
320 long recurse_jmp
[JMP_BUF_LEN
];
321 unsigned long offset
;
325 unsigned long timeout
;
329 mtmsr(msr
& ~MSR_EE
); /* disable interrupts */
331 bp
= in_breakpoint_table(regs
->nip
, &offset
);
333 regs
->nip
= bp
->address
+ offset
;
334 atomic_dec(&bp
->ref_count
);
340 cpu
= smp_processor_id();
341 if (cpu_isset(cpu
, cpus_in_xmon
)) {
344 printf("cpu 0x%x: Exception %lx %s in xmon, "
345 "returning to main loop\n",
346 cpu
, regs
->trap
, getvecname(TRAP(regs
)));
347 release_output_lock();
348 longjmp(xmon_fault_jmp
[cpu
], 1);
351 if (setjmp(recurse_jmp
) != 0) {
352 if (!in_xmon
|| !xmon_gate
) {
354 printf("xmon: WARNING: bad recursive fault "
355 "on cpu 0x%x\n", cpu
);
356 release_output_lock();
359 secondary
= !(xmon_taken
&& cpu
== xmon_owner
);
363 xmon_fault_jmp
[cpu
] = recurse_jmp
;
364 cpu_set(cpu
, cpus_in_xmon
);
367 if ((regs
->msr
& (MSR_IR
|MSR_PR
|MSR_SF
)) == (MSR_IR
|MSR_SF
))
368 bp
= at_breakpoint(regs
->nip
);
369 if (bp
|| (regs
->msr
& MSR_RI
) == 0)
376 printf("cpu 0x%x stopped at breakpoint 0x%x (",
378 xmon_print_symbol(regs
->nip
, " ", ")\n");
380 if ((regs
->msr
& MSR_RI
) == 0)
381 printf("WARNING: exception is not recoverable, "
383 release_output_lock();
388 while (secondary
&& !xmon_gate
) {
392 secondary
= test_and_set_bit(0, &in_xmon
);
397 if (!secondary
&& !xmon_gate
) {
398 /* we are the first cpu to come in */
399 /* interrupt other cpu(s) */
400 int ncpus
= num_online_cpus();
405 smp_send_debugger_break(MSG_ALL_BUT_SELF
);
406 /* wait for other cpus to come in */
407 for (timeout
= 100000000; timeout
!= 0; --timeout
) {
408 if (cpus_weight(cpus_in_xmon
) >= ncpus
)
414 disable_surveillance();
415 /* for breakpoint or single step, print the current instr. */
416 if (bp
|| TRAP(regs
) == 0xd00)
417 ppc_inst_dump(regs
->nip
, 1, 0);
418 printf("enter ? for help\n");
427 if (cpu
== xmon_owner
) {
428 if (!test_and_set_bit(0, &xmon_taken
)) {
433 while (cpu
== xmon_owner
)
447 /* have switched to some other cpu */
452 cpu_clear(cpu
, cpus_in_xmon
);
453 xmon_fault_jmp
[cpu
] = NULL
;
455 /* UP is simple... */
457 printf("Exception %lx %s in xmon, returning to main loop\n",
458 regs
->trap
, getvecname(TRAP(regs
)));
459 longjmp(xmon_fault_jmp
[0], 1);
461 if (setjmp(recurse_jmp
) == 0) {
462 xmon_fault_jmp
[0] = recurse_jmp
;
466 bp
= at_breakpoint(regs
->nip
);
468 printf("Stopped at breakpoint %x (", BP_NUM(bp
));
469 xmon_print_symbol(regs
->nip
, " ", ")\n");
471 if ((regs
->msr
& MSR_RI
) == 0)
472 printf("WARNING: exception is not recoverable, "
475 disable_surveillance();
476 /* for breakpoint or single step, print the current instr. */
477 if (bp
|| TRAP(regs
) == 0xd00)
478 ppc_inst_dump(regs
->nip
, 1, 0);
479 printf("enter ? for help\n");
488 if ((regs
->msr
& (MSR_IR
|MSR_PR
|MSR_SF
)) == (MSR_IR
|MSR_SF
)) {
489 bp
= at_breakpoint(regs
->nip
);
491 int stepped
= emulate_step(regs
, bp
->instr
[0]);
493 regs
->nip
= (unsigned long) &bp
->instr
[0];
494 atomic_inc(&bp
->ref_count
);
495 } else if (stepped
< 0) {
496 printf("Couldn't single-step %s instruction\n",
497 (IS_RFID(bp
->instr
[0])? "rfid": "mtmsrd"));
504 mtmsr(msr
); /* restore interrupt enable */
509 int xmon(struct pt_regs
*excp
)
514 xmon_save_regs(®s
);
517 return xmon_core(excp
, 0);
522 xmon_irq(int irq
, void *d
, struct pt_regs
*regs
)
525 local_irq_save(flags
);
526 printf("Keyboard interrupt\n");
528 local_irq_restore(flags
);
532 static int xmon_bpt(struct pt_regs
*regs
)
535 unsigned long offset
;
537 if ((regs
->msr
& (MSR_IR
|MSR_PR
|MSR_SF
)) != (MSR_IR
|MSR_SF
))
540 /* Are we at the trap at bp->instr[1] for some bp? */
541 bp
= in_breakpoint_table(regs
->nip
, &offset
);
542 if (bp
!= NULL
&& offset
== 4) {
543 regs
->nip
= bp
->address
+ 4;
544 atomic_dec(&bp
->ref_count
);
548 /* Are we at a breakpoint? */
549 bp
= at_breakpoint(regs
->nip
);
558 static int xmon_sstep(struct pt_regs
*regs
)
566 static int xmon_dabr_match(struct pt_regs
*regs
)
568 if ((regs
->msr
& (MSR_IR
|MSR_PR
|MSR_SF
)) != (MSR_IR
|MSR_SF
))
570 if (dabr
.enabled
== 0)
576 static int xmon_iabr_match(struct pt_regs
*regs
)
578 if ((regs
->msr
& (MSR_IR
|MSR_PR
|MSR_SF
)) != (MSR_IR
|MSR_SF
))
586 static int xmon_ipi(struct pt_regs
*regs
)
589 if (in_xmon
&& !cpu_isset(smp_processor_id(), cpus_in_xmon
))
595 static int xmon_fault_handler(struct pt_regs
*regs
)
598 unsigned long offset
;
600 if (in_xmon
&& catch_memory_errors
)
601 handle_fault(regs
); /* doesn't return */
603 if ((regs
->msr
& (MSR_IR
|MSR_PR
|MSR_SF
)) == (MSR_IR
|MSR_SF
)) {
604 bp
= in_breakpoint_table(regs
->nip
, &offset
);
606 regs
->nip
= bp
->address
+ offset
;
607 atomic_dec(&bp
->ref_count
);
614 static struct bpt
*at_breakpoint(unsigned long pc
)
620 for (i
= 0; i
< NBPTS
; ++i
, ++bp
)
621 if (bp
->enabled
&& pc
== bp
->address
)
626 static struct bpt
*in_breakpoint_table(unsigned long nip
, unsigned long *offp
)
630 off
= nip
- (unsigned long) bpts
;
631 if (off
>= sizeof(bpts
))
633 off
%= sizeof(struct bpt
);
634 if (off
!= offsetof(struct bpt
, instr
[0])
635 && off
!= offsetof(struct bpt
, instr
[1]))
637 *offp
= off
- offsetof(struct bpt
, instr
[0]);
638 return (struct bpt
*) (nip
- off
);
641 static struct bpt
*new_breakpoint(unsigned long a
)
646 bp
= at_breakpoint(a
);
650 for (bp
= bpts
; bp
< &bpts
[NBPTS
]; ++bp
) {
651 if (!bp
->enabled
&& atomic_read(&bp
->ref_count
) == 0) {
653 bp
->instr
[1] = bpinstr
;
654 store_inst(&bp
->instr
[1]);
659 printf("Sorry, no free breakpoints. Please clear one first.\n");
663 static void insert_bpts(void)
669 for (i
= 0; i
< NBPTS
; ++i
, ++bp
) {
670 if ((bp
->enabled
& (BP_TRAP
|BP_IABR
)) == 0)
672 if (mread(bp
->address
, &bp
->instr
[0], 4) != 4) {
673 printf("Couldn't read instruction at %lx, "
674 "disabling breakpoint there\n", bp
->address
);
678 if (IS_MTMSRD(bp
->instr
[0]) || IS_RFID(bp
->instr
[0])) {
679 printf("Breakpoint at %lx is on an mtmsrd or rfid "
680 "instruction, disabling it\n", bp
->address
);
684 store_inst(&bp
->instr
[0]);
685 if (bp
->enabled
& BP_IABR
)
687 if (mwrite(bp
->address
, &bpinstr
, 4) != 4) {
688 printf("Couldn't write instruction at %lx, "
689 "disabling breakpoint there\n", bp
->address
);
690 bp
->enabled
&= ~BP_TRAP
;
693 store_inst((void *)bp
->address
);
697 static void insert_cpu_bpts(void)
700 set_dabr(dabr
.address
| (dabr
.enabled
& 7));
701 if (iabr
&& cpu_has_feature(CPU_FTR_IABR
))
702 mtspr(SPRN_IABR
, iabr
->address
703 | (iabr
->enabled
& (BP_IABR
|BP_IABR_TE
)));
706 static void remove_bpts(void)
713 for (i
= 0; i
< NBPTS
; ++i
, ++bp
) {
714 if ((bp
->enabled
& (BP_TRAP
|BP_IABR
)) != BP_TRAP
)
716 if (mread(bp
->address
, &instr
, 4) == 4
718 && mwrite(bp
->address
, &bp
->instr
, 4) != 4)
719 printf("Couldn't remove breakpoint at %lx\n",
722 store_inst((void *)bp
->address
);
726 static void remove_cpu_bpts(void)
729 if (cpu_has_feature(CPU_FTR_IABR
))
733 /* Command interpreting routine */
734 static char *last_cmd
;
737 cmds(struct pt_regs
*excp
)
745 printf("%x:", smp_processor_id());
746 #endif /* CONFIG_SMP */
752 if (last_cmd
== NULL
)
754 take_input(last_cmd
);
788 prregs(excp
); /* print regs */
810 printf(" <no input ...>\n");
832 #ifdef CONFIG_PPC_STD_MMU
838 printf("Unrecognized command: ");
840 if (' ' < cmd
&& cmd
<= '~')
843 printf("\\x%x", cmd
);
845 } while (cmd
!= '\n');
846 printf(" (type ? for help)\n");
853 * Step a single instruction.
854 * Some instructions we emulate, others we execute with MSR_SE set.
856 static int do_step(struct pt_regs
*regs
)
861 /* check we are in 64-bit kernel mode, translation enabled */
862 if ((regs
->msr
& (MSR_SF
|MSR_PR
|MSR_IR
)) == (MSR_SF
|MSR_IR
)) {
863 if (mread(regs
->nip
, &instr
, 4) == 4) {
864 stepped
= emulate_step(regs
, instr
);
866 printf("Couldn't single-step %s instruction\n",
867 (IS_RFID(instr
)? "rfid": "mtmsrd"));
871 regs
->trap
= 0xd00 | (regs
->trap
& 1);
872 printf("stepped to ");
873 xmon_print_symbol(regs
->nip
, " ", "\n");
874 ppc_inst_dump(regs
->nip
, 1, 0);
883 static void bootcmds(void)
889 ppc_md
.restart(NULL
);
896 static int cpu_cmd(void)
903 if (!scanhex(&cpu
)) {
904 /* print cpus waiting or in xmon */
905 printf("cpus stopped:");
907 for (cpu
= 0; cpu
< NR_CPUS
; ++cpu
) {
908 if (cpu_isset(cpu
, cpus_in_xmon
)) {
914 printf("-%x", cpu
- 1);
919 printf("-%x", NR_CPUS
- 1);
923 /* try to switch to cpu specified */
924 if (!cpu_isset(cpu
, cpus_in_xmon
)) {
925 printf("cpu 0x%x isn't in xmon\n", cpu
);
932 while (!xmon_taken
) {
933 if (--timeout
== 0) {
934 if (test_and_set_bit(0, &xmon_taken
))
936 /* take control back */
938 xmon_owner
= smp_processor_id();
939 printf("cpu %u didn't take control\n", cpu
);
947 #endif /* CONFIG_SMP */
950 static unsigned short fcstab
[256] = {
951 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
952 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
953 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
954 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
955 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
956 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
957 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
958 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
959 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
960 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
961 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
962 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
963 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
964 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
965 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
966 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
967 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
968 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
969 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
970 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
971 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
972 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
973 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
974 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
975 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
976 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
977 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
978 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
979 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
980 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
981 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
982 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
985 #define FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
996 if (!scanhex(&ncsum
))
999 for (i
= 0; i
< ncsum
; ++i
) {
1000 if (mread(adrs
+i
, &v
, 1) == 0) {
1001 printf("csum stopped at %x\n", adrs
+i
);
1006 printf("%x\n", fcs
);
1010 * Check if this is a suitable place to put a breakpoint.
1012 static long check_bp_loc(unsigned long addr
)
1017 if (!is_kernel_addr(addr
)) {
1018 printf("Breakpoints may only be placed at kernel addresses\n");
1021 if (!mread(addr
, &instr
, sizeof(instr
))) {
1022 printf("Can't read instruction at address %lx\n", addr
);
1025 if (IS_MTMSRD(instr
) || IS_RFID(instr
)) {
1026 printf("Breakpoints may not be placed on mtmsrd or rfid "
1033 static char *breakpoint_help_string
=
1034 "Breakpoint command usage:\n"
1035 "b show breakpoints\n"
1036 "b <addr> [cnt] set breakpoint at given instr addr\n"
1037 "bc clear all breakpoints\n"
1038 "bc <n/addr> clear breakpoint number n or at addr\n"
1039 "bi <addr> [cnt] set hardware instr breakpoint (POWER3/RS64 only)\n"
1040 "bd <addr> [cnt] set hardware data breakpoint\n"
1050 const char badaddr
[] = "Only kernel addresses are permitted "
1051 "for breakpoints\n";
1056 case 'd': /* bd - hardware data breakpoint */
1061 else if (cmd
== 'w')
1067 if (scanhex(&dabr
.address
)) {
1068 if (!is_kernel_addr(dabr
.address
)) {
1073 dabr
.enabled
= mode
| BP_DABR
;
1077 case 'i': /* bi - hardware instr breakpoint */
1078 if (!cpu_has_feature(CPU_FTR_IABR
)) {
1079 printf("Hardware instruction breakpoint "
1080 "not supported on this cpu\n");
1084 iabr
->enabled
&= ~(BP_IABR
| BP_IABR_TE
);
1089 if (!check_bp_loc(a
))
1091 bp
= new_breakpoint(a
);
1093 bp
->enabled
|= BP_IABR
| BP_IABR_TE
;
1101 /* clear all breakpoints */
1102 for (i
= 0; i
< NBPTS
; ++i
)
1103 bpts
[i
].enabled
= 0;
1106 printf("All breakpoints cleared\n");
1110 if (a
<= NBPTS
&& a
>= 1) {
1111 /* assume a breakpoint number */
1112 bp
= &bpts
[a
-1]; /* bp nums are 1 based */
1114 /* assume a breakpoint address */
1115 bp
= at_breakpoint(a
);
1117 printf("No breakpoint at %x\n", a
);
1122 printf("Cleared breakpoint %x (", BP_NUM(bp
));
1123 xmon_print_symbol(bp
->address
, " ", ")\n");
1131 printf(breakpoint_help_string
);
1136 /* print all breakpoints */
1137 printf(" type address\n");
1139 printf(" data "REG
" [", dabr
.address
);
1140 if (dabr
.enabled
& 1)
1142 if (dabr
.enabled
& 2)
1146 for (bp
= bpts
; bp
< &bpts
[NBPTS
]; ++bp
) {
1149 printf("%2x %s ", BP_NUM(bp
),
1150 (bp
->enabled
& BP_IABR
)? "inst": "trap");
1151 xmon_print_symbol(bp
->address
, " ", "\n");
1156 if (!check_bp_loc(a
))
1158 bp
= new_breakpoint(a
);
1160 bp
->enabled
|= BP_TRAP
;
1165 /* Very cheap human name for vector lookup. */
1167 const char *getvecname(unsigned long vec
)
1172 case 0x100: ret
= "(System Reset)"; break;
1173 case 0x200: ret
= "(Machine Check)"; break;
1174 case 0x300: ret
= "(Data Access)"; break;
1175 case 0x380: ret
= "(Data SLB Access)"; break;
1176 case 0x400: ret
= "(Instruction Access)"; break;
1177 case 0x480: ret
= "(Instruction SLB Access)"; break;
1178 case 0x500: ret
= "(Hardware Interrupt)"; break;
1179 case 0x600: ret
= "(Alignment)"; break;
1180 case 0x700: ret
= "(Program Check)"; break;
1181 case 0x800: ret
= "(FPU Unavailable)"; break;
1182 case 0x900: ret
= "(Decrementer)"; break;
1183 case 0xc00: ret
= "(System Call)"; break;
1184 case 0xd00: ret
= "(Single Step)"; break;
1185 case 0xf00: ret
= "(Performance Monitor)"; break;
1186 case 0xf20: ret
= "(Altivec Unavailable)"; break;
1187 case 0x1300: ret
= "(Instruction Breakpoint)"; break;
1193 static void get_function_bounds(unsigned long pc
, unsigned long *startp
,
1194 unsigned long *endp
)
1196 unsigned long size
, offset
;
1200 *startp
= *endp
= 0;
1203 if (setjmp(bus_error_jmp
) == 0) {
1204 catch_memory_errors
= 1;
1206 name
= kallsyms_lookup(pc
, &size
, &offset
, &modname
, tmpstr
);
1208 *startp
= pc
- offset
;
1209 *endp
= pc
- offset
+ size
;
1213 catch_memory_errors
= 0;
1216 static int xmon_depth_to_print
= 64;
1219 #define LRSAVE_OFFSET 0x10
1220 #define REG_FRAME_MARKER 0x7265677368657265ul /* "regshere" */
1221 #define MARKER_OFFSET 0x60
1222 #define REGS_OFFSET 0x70
1224 #define LRSAVE_OFFSET 4
1225 #define REG_FRAME_MARKER 0x72656773
1226 #define MARKER_OFFSET 8
1227 #define REGS_OFFSET 16
1230 static void xmon_show_stack(unsigned long sp
, unsigned long lr
,
1234 unsigned long newsp
;
1235 unsigned long marker
;
1237 struct pt_regs regs
;
1240 if (sp
< PAGE_OFFSET
) {
1242 printf("SP (%lx) is in userspace\n", sp
);
1246 if (!mread(sp
+ LRSAVE_OFFSET
, &ip
, sizeof(unsigned long))
1247 || !mread(sp
, &newsp
, sizeof(unsigned long))) {
1248 printf("Couldn't read stack frame at %lx\n", sp
);
1253 * For the first stack frame, try to work out if
1254 * LR and/or the saved LR value in the bottommost
1255 * stack frame are valid.
1257 if ((pc
| lr
) != 0) {
1258 unsigned long fnstart
, fnend
;
1259 unsigned long nextip
;
1262 get_function_bounds(pc
, &fnstart
, &fnend
);
1265 mread(newsp
+ LRSAVE_OFFSET
, &nextip
,
1266 sizeof(unsigned long));
1268 if (lr
< PAGE_OFFSET
1269 || (fnstart
<= lr
&& lr
< fnend
))
1271 } else if (lr
== nextip
) {
1273 } else if (lr
>= PAGE_OFFSET
1274 && !(fnstart
<= lr
&& lr
< fnend
)) {
1275 printf("[link register ] ");
1276 xmon_print_symbol(lr
, " ", "\n");
1279 printf("["REG
"] ", sp
);
1280 xmon_print_symbol(ip
, " ", " (unreliable)\n");
1285 printf("["REG
"] ", sp
);
1286 xmon_print_symbol(ip
, " ", "\n");
1289 /* Look for "regshere" marker to see if this is
1290 an exception frame. */
1291 if (mread(sp
+ MARKER_OFFSET
, &marker
, sizeof(unsigned long))
1292 && marker
== REG_FRAME_MARKER
) {
1293 if (mread(sp
+ REGS_OFFSET
, ®s
, sizeof(regs
))
1295 printf("Couldn't read registers at %lx\n",
1299 printf("--- Exception: %lx %s at ", regs
.trap
,
1300 getvecname(TRAP(®s
)));
1303 xmon_print_symbol(pc
, " ", "\n");
1310 } while (count
++ < xmon_depth_to_print
);
1313 static void backtrace(struct pt_regs
*excp
)
1318 xmon_show_stack(sp
, 0, 0);
1320 xmon_show_stack(excp
->gpr
[1], excp
->link
, excp
->nip
);
1324 static void print_bug_trap(struct pt_regs
*regs
)
1326 struct bug_entry
*bug
;
1329 if (regs
->msr
& MSR_PR
)
1330 return; /* not in kernel */
1331 addr
= regs
->nip
; /* address of trap instruction */
1332 if (addr
< PAGE_OFFSET
)
1334 bug
= find_bug(regs
->nip
);
1337 if (bug
->line
& BUG_WARNING_TRAP
)
1340 printf("kernel BUG in %s at %s:%d!\n",
1341 bug
->function
, bug
->file
, (unsigned int)bug
->line
);
1344 void excprint(struct pt_regs
*fp
)
1349 printf("cpu 0x%x: ", smp_processor_id());
1350 #endif /* CONFIG_SMP */
1353 printf("Vector: %lx %s at [%lx]\n", fp
->trap
, getvecname(trap
), fp
);
1355 xmon_print_symbol(fp
->nip
, ": ", "\n");
1357 printf(" lr: ", fp
->link
);
1358 xmon_print_symbol(fp
->link
, ": ", "\n");
1360 printf(" sp: %lx\n", fp
->gpr
[1]);
1361 printf(" msr: %lx\n", fp
->msr
);
1363 if (trap
== 0x300 || trap
== 0x380 || trap
== 0x600) {
1364 printf(" dar: %lx\n", fp
->dar
);
1366 printf(" dsisr: %lx\n", fp
->dsisr
);
1369 printf(" current = 0x%lx\n", current
);
1371 printf(" paca = 0x%lx\n", get_paca());
1374 printf(" pid = %ld, comm = %s\n",
1375 current
->pid
, current
->comm
);
1382 void prregs(struct pt_regs
*fp
)
1386 struct pt_regs regs
;
1388 if (scanhex(&base
)) {
1389 if (setjmp(bus_error_jmp
) == 0) {
1390 catch_memory_errors
= 1;
1392 regs
= *(struct pt_regs
*)base
;
1396 catch_memory_errors
= 0;
1397 printf("*** Error reading registers from "REG
"\n",
1401 catch_memory_errors
= 0;
1406 if (FULL_REGS(fp
)) {
1407 for (n
= 0; n
< 16; ++n
)
1408 printf("R%.2ld = "REG
" R%.2ld = "REG
"\n",
1409 n
, fp
->gpr
[n
], n
+16, fp
->gpr
[n
+16]);
1411 for (n
= 0; n
< 7; ++n
)
1412 printf("R%.2ld = "REG
" R%.2ld = "REG
"\n",
1413 n
, fp
->gpr
[n
], n
+7, fp
->gpr
[n
+7]);
1416 for (n
= 0; n
< 32; ++n
) {
1417 printf("R%.2d = %.8x%s", n
, fp
->gpr
[n
],
1418 (n
& 3) == 3? "\n": " ");
1419 if (n
== 12 && !FULL_REGS(fp
)) {
1426 xmon_print_symbol(fp
->nip
, " ", "\n");
1428 xmon_print_symbol(fp
->link
, " ", "\n");
1429 printf("msr = "REG
" cr = %.8lx\n", fp
->msr
, fp
->ccr
);
1430 printf("ctr = "REG
" xer = "REG
" trap = %4lx\n",
1431 fp
->ctr
, fp
->xer
, fp
->trap
);
1433 if (trap
== 0x300 || trap
== 0x380 || trap
== 0x600)
1434 printf("dar = "REG
" dsisr = %.8lx\n", fp
->dar
, fp
->dsisr
);
1437 void cacheflush(void)
1440 unsigned long nflush
;
1445 scanhex((void *)&adrs
);
1450 nflush
= (nflush
+ L1_CACHE_BYTES
- 1) / L1_CACHE_BYTES
;
1451 if (setjmp(bus_error_jmp
) == 0) {
1452 catch_memory_errors
= 1;
1456 for (; nflush
> 0; --nflush
, adrs
+= L1_CACHE_BYTES
)
1457 cflush((void *) adrs
);
1459 for (; nflush
> 0; --nflush
, adrs
+= L1_CACHE_BYTES
)
1460 cinval((void *) adrs
);
1463 /* wait a little while to see if we get a machine check */
1466 catch_memory_errors
= 0;
1472 unsigned int instrs
[2];
1473 unsigned long (*code
)(void);
1474 unsigned long ret
= -1UL;
1476 unsigned long opd
[3];
1478 opd
[0] = (unsigned long)instrs
;
1481 code
= (unsigned long (*)(void)) opd
;
1483 code
= (unsigned long (*)(void)) instrs
;
1486 /* mfspr r3,n; blr */
1487 instrs
[0] = 0x7c6002a6 + ((n
& 0x1F) << 16) + ((n
& 0x3e0) << 6);
1488 instrs
[1] = 0x4e800020;
1490 store_inst(instrs
+1);
1492 if (setjmp(bus_error_jmp
) == 0) {
1493 catch_memory_errors
= 1;
1499 /* wait a little while to see if we get a machine check */
1508 write_spr(int n
, unsigned long val
)
1510 unsigned int instrs
[2];
1511 unsigned long (*code
)(unsigned long);
1513 unsigned long opd
[3];
1515 opd
[0] = (unsigned long)instrs
;
1518 code
= (unsigned long (*)(unsigned long)) opd
;
1520 code
= (unsigned long (*)(unsigned long)) instrs
;
1523 instrs
[0] = 0x7c6003a6 + ((n
& 0x1F) << 16) + ((n
& 0x3e0) << 6);
1524 instrs
[1] = 0x4e800020;
1526 store_inst(instrs
+1);
1528 if (setjmp(bus_error_jmp
) == 0) {
1529 catch_memory_errors
= 1;
1535 /* wait a little while to see if we get a machine check */
1541 static unsigned long regno
;
1542 extern char exc_prolog
;
1543 extern char dec_exc
;
1545 void super_regs(void)
1549 #ifdef CONFIG_PPC_ISERIES
1550 struct paca_struct
*ptrPaca
= NULL
;
1551 struct lppaca
*ptrLpPaca
= NULL
;
1552 struct ItLpRegSave
*ptrLpRegSave
= NULL
;
1557 unsigned long sp
, toc
;
1558 asm("mr %0,1" : "=r" (sp
) :);
1559 asm("mr %0,2" : "=r" (toc
) :);
1561 printf("msr = "REG
" sprg0= "REG
"\n",
1562 mfmsr(), mfspr(SPRN_SPRG0
));
1563 printf("pvr = "REG
" sprg1= "REG
"\n",
1564 mfspr(SPRN_PVR
), mfspr(SPRN_SPRG1
));
1565 printf("dec = "REG
" sprg2= "REG
"\n",
1566 mfspr(SPRN_DEC
), mfspr(SPRN_SPRG2
));
1567 printf("sp = "REG
" sprg3= "REG
"\n", sp
, mfspr(SPRN_SPRG3
));
1568 printf("toc = "REG
" dar = "REG
"\n", toc
, mfspr(SPRN_DAR
));
1569 #ifdef CONFIG_PPC_ISERIES
1570 // Dump out relevant Paca data areas.
1572 ptrPaca
= get_paca();
1574 printf(" Local Processor Control Area (LpPaca): \n");
1575 ptrLpPaca
= ptrPaca
->lppaca_ptr
;
1576 printf(" Saved Srr0=%.16lx Saved Srr1=%.16lx \n",
1577 ptrLpPaca
->saved_srr0
, ptrLpPaca
->saved_srr1
);
1578 printf(" Saved Gpr3=%.16lx Saved Gpr4=%.16lx \n",
1579 ptrLpPaca
->saved_gpr3
, ptrLpPaca
->saved_gpr4
);
1580 printf(" Saved Gpr5=%.16lx \n", ptrLpPaca
->saved_gpr5
);
1582 printf(" Local Processor Register Save Area (LpRegSave): \n");
1583 ptrLpRegSave
= ptrPaca
->reg_save_ptr
;
1584 printf(" Saved Sprg0=%.16lx Saved Sprg1=%.16lx \n",
1585 ptrLpRegSave
->xSPRG0
, ptrLpRegSave
->xSPRG0
);
1586 printf(" Saved Sprg2=%.16lx Saved Sprg3=%.16lx \n",
1587 ptrLpRegSave
->xSPRG2
, ptrLpRegSave
->xSPRG3
);
1588 printf(" Saved Msr =%.16lx Saved Nia =%.16lx \n",
1589 ptrLpRegSave
->xMSR
, ptrLpRegSave
->xNIA
);
1598 val
= read_spr(regno
);
1600 write_spr(regno
, val
);
1603 printf("spr %lx = %lx\n", regno
, read_spr(regno
));
1610 * Stuff for reading and writing memory safely
1613 mread(unsigned long adrs
, void *buf
, int size
)
1619 if (setjmp(bus_error_jmp
) == 0) {
1620 catch_memory_errors
= 1;
1626 *(u16
*)q
= *(u16
*)p
;
1629 *(u32
*)q
= *(u32
*)p
;
1632 *(u64
*)q
= *(u64
*)p
;
1635 for( ; n
< size
; ++n
) {
1641 /* wait a little while to see if we get a machine check */
1645 catch_memory_errors
= 0;
1650 mwrite(unsigned long adrs
, void *buf
, int size
)
1656 if (setjmp(bus_error_jmp
) == 0) {
1657 catch_memory_errors
= 1;
1663 *(u16
*)p
= *(u16
*)q
;
1666 *(u32
*)p
= *(u32
*)q
;
1669 *(u64
*)p
= *(u64
*)q
;
1672 for ( ; n
< size
; ++n
) {
1678 /* wait a little while to see if we get a machine check */
1682 printf("*** Error writing address %x\n", adrs
+ n
);
1684 catch_memory_errors
= 0;
1688 static int fault_type
;
1689 static int fault_except
;
1690 static char *fault_chars
[] = { "--", "**", "##" };
1692 static int handle_fault(struct pt_regs
*regs
)
1694 fault_except
= TRAP(regs
);
1695 switch (TRAP(regs
)) {
1707 longjmp(bus_error_jmp
, 1);
1712 #define SWAP(a, b, t) ((t) = (a), (a) = (b), (b) = (t))
1715 byterev(unsigned char *val
, int size
)
1721 SWAP(val
[0], val
[1], t
);
1724 SWAP(val
[0], val
[3], t
);
1725 SWAP(val
[1], val
[2], t
);
1727 case 8: /* is there really any use for this? */
1728 SWAP(val
[0], val
[7], t
);
1729 SWAP(val
[1], val
[6], t
);
1730 SWAP(val
[2], val
[5], t
);
1731 SWAP(val
[3], val
[4], t
);
1739 static char *memex_help_string
=
1740 "Memory examine command usage:\n"
1741 "m [addr] [flags] examine/change memory\n"
1742 " addr is optional. will start where left off.\n"
1743 " flags may include chars from this set:\n"
1744 " b modify by bytes (default)\n"
1745 " w modify by words (2 byte)\n"
1746 " l modify by longs (4 byte)\n"
1747 " d modify by doubleword (8 byte)\n"
1748 " r toggle reverse byte order mode\n"
1749 " n do not read memory (for i/o spaces)\n"
1750 " . ok to read (default)\n"
1751 "NOTE: flags are saved as defaults\n"
1754 static char *memex_subcmd_help_string
=
1755 "Memory examine subcommands:\n"
1756 " hexval write this val to current location\n"
1757 " 'string' write chars from string to this location\n"
1758 " ' increment address\n"
1759 " ^ decrement address\n"
1760 " / increment addr by 0x10. //=0x100, ///=0x1000, etc\n"
1761 " \\ decrement addr by 0x10. \\\\=0x100, \\\\\\=0x1000, etc\n"
1762 " ` clear no-read flag\n"
1763 " ; stay at this addr\n"
1764 " v change to byte mode\n"
1765 " w change to word (2 byte) mode\n"
1766 " l change to long (4 byte) mode\n"
1767 " u change to doubleword (8 byte) mode\n"
1768 " m addr change current addr\n"
1769 " n toggle no-read flag\n"
1770 " r toggle byte reverse flag\n"
1771 " < count back up count bytes\n"
1772 " > count skip forward count bytes\n"
1773 " x exit this mode\n"
1779 int cmd
, inc
, i
, nslash
;
1781 unsigned char val
[16];
1783 scanhex((void *)&adrs
);
1786 printf(memex_help_string
);
1792 while ((cmd
= skipbl()) != '\n') {
1794 case 'b': size
= 1; break;
1795 case 'w': size
= 2; break;
1796 case 'l': size
= 4; break;
1797 case 'd': size
= 8; break;
1798 case 'r': brev
= !brev
; break;
1799 case 'n': mnoread
= 1; break;
1800 case '.': mnoread
= 0; break;
1809 n
= mread(adrs
, val
, size
);
1810 printf(REG
"%c", adrs
, brev
? 'r': ' ');
1815 for (i
= 0; i
< n
; ++i
)
1816 printf("%.2x", val
[i
]);
1817 for (; i
< size
; ++i
)
1818 printf("%s", fault_chars
[fault_type
]);
1825 for (i
= 0; i
< size
; ++i
)
1826 val
[i
] = n
>> (i
* 8);
1829 mwrite(adrs
, val
, size
);
1842 else if( n
== '\'' )
1844 for (i
= 0; i
< size
; ++i
)
1845 val
[i
] = n
>> (i
* 8);
1848 mwrite(adrs
, val
, size
);
1885 adrs
-= 1 << nslash
;
1889 adrs
+= 1 << nslash
;
1893 adrs
+= 1 << -nslash
;
1897 adrs
-= 1 << -nslash
;
1900 scanhex((void *)&adrs
);
1919 printf(memex_subcmd_help_string
);
1934 case 'n': c
= '\n'; break;
1935 case 'r': c
= '\r'; break;
1936 case 'b': c
= '\b'; break;
1937 case 't': c
= '\t'; break;
1942 static void xmon_rawdump (unsigned long adrs
, long ndump
)
1945 unsigned char temp
[16];
1947 for (n
= ndump
; n
> 0;) {
1949 nr
= mread(adrs
, temp
, r
);
1951 for (m
= 0; m
< r
; ++m
) {
1953 printf("%.2x", temp
[m
]);
1955 printf("%s", fault_chars
[fault_type
]);
1964 #define isxdigit(c) (('0' <= (c) && (c) <= '9') \
1965 || ('a' <= (c) && (c) <= 'f') \
1966 || ('A' <= (c) && (c) <= 'F'))
1973 if ((isxdigit(c
) && c
!= 'f' && c
!= 'd') || c
== '\n')
1975 scanhex((void *)&adrs
);
1982 else if (nidump
> MAX_DUMP
)
1984 adrs
+= ppc_inst_dump(adrs
, nidump
, 1);
1986 } else if (c
== 'r') {
1990 xmon_rawdump(adrs
, ndump
);
1997 else if (ndump
> MAX_DUMP
)
1999 prdump(adrs
, ndump
);
2006 prdump(unsigned long adrs
, long ndump
)
2008 long n
, m
, c
, r
, nr
;
2009 unsigned char temp
[16];
2011 for (n
= ndump
; n
> 0;) {
2015 nr
= mread(adrs
, temp
, r
);
2017 for (m
= 0; m
< r
; ++m
) {
2018 if ((m
& (sizeof(long) - 1)) == 0 && m
> 0)
2021 printf("%.2x", temp
[m
]);
2023 printf("%s", fault_chars
[fault_type
]);
2025 for (; m
< 16; ++m
) {
2026 if ((m
& (sizeof(long) - 1)) == 0)
2031 for (m
= 0; m
< r
; ++m
) {
2034 putchar(' ' <= c
&& c
<= '~'? c
: '.');
2048 ppc_inst_dump(unsigned long adr
, long count
, int praddr
)
2051 unsigned long first_adr
;
2052 unsigned long inst
, last_inst
= 0;
2053 unsigned char val
[4];
2056 for (first_adr
= adr
; count
> 0; --count
, adr
+= 4) {
2057 nr
= mread(adr
, val
, 4);
2060 const char *x
= fault_chars
[fault_type
];
2061 printf(REG
" %s%s%s%s\n", adr
, x
, x
, x
, x
);
2065 inst
= GETWORD(val
);
2066 if (adr
> first_adr
&& inst
== last_inst
) {
2076 printf(REG
" %.8x", adr
, inst
);
2078 print_insn_powerpc(inst
, adr
, 0); /* always returns 4 */
2081 return adr
- first_adr
;
2085 print_address(unsigned long addr
)
2087 xmon_print_symbol(addr
, "\t# ", "");
2092 * Memory operations - move, set, print differences
2094 static unsigned long mdest
; /* destination address */
2095 static unsigned long msrc
; /* source address */
2096 static unsigned long mval
; /* byte value to set memory to */
2097 static unsigned long mcount
; /* # bytes to affect */
2098 static unsigned long mdiffs
; /* max # differences to print */
2103 scanhex((void *)&mdest
);
2104 if( termch
!= '\n' )
2106 scanhex((void *)(cmd
== 's'? &mval
: &msrc
));
2107 if( termch
!= '\n' )
2109 scanhex((void *)&mcount
);
2112 memmove((void *)mdest
, (void *)msrc
, mcount
);
2115 memset((void *)mdest
, mval
, mcount
);
2118 if( termch
!= '\n' )
2120 scanhex((void *)&mdiffs
);
2121 memdiffs((unsigned char *)mdest
, (unsigned char *)msrc
, mcount
, mdiffs
);
2127 memdiffs(unsigned char *p1
, unsigned char *p2
, unsigned nb
, unsigned maxpr
)
2132 for( n
= nb
; n
> 0; --n
)
2133 if( *p1
++ != *p2
++ )
2134 if( ++prt
<= maxpr
)
2135 printf("%.16x %.2x # %.16x %.2x\n", p1
- 1,
2136 p1
[-1], p2
- 1, p2
[-1]);
2138 printf("Total of %d differences\n", prt
);
2141 static unsigned mend
;
2142 static unsigned mask
;
2148 unsigned char val
[4];
2151 scanhex((void *)&mdest
);
2152 if (termch
!= '\n') {
2154 scanhex((void *)&mend
);
2155 if (termch
!= '\n') {
2157 scanhex((void *)&mval
);
2159 if (termch
!= '\n') termch
= 0;
2160 scanhex((void *)&mask
);
2164 for (a
= mdest
; a
< mend
; a
+= 4) {
2165 if (mread(a
, val
, 4) == 4
2166 && ((GETWORD(val
) ^ mval
) & mask
) == 0) {
2167 printf("%.16x: %.16x\n", a
, GETWORD(val
));
2174 static unsigned long mskip
= 0x1000;
2175 static unsigned long mlim
= 0xffffffff;
2185 if (termch
!= '\n') termch
= 0;
2187 if (termch
!= '\n') termch
= 0;
2190 for (a
= mdest
; a
< mlim
; a
+= mskip
) {
2191 ok
= mread(a
, &v
, 1);
2193 printf("%.8x .. ", a
);
2194 } else if (!ok
&& ook
)
2195 printf("%.8x\n", a
- mskip
);
2201 printf("%.8x\n", a
- mskip
);
2206 unsigned long args
[8];
2209 typedef unsigned long (*callfunc_t
)(unsigned long, unsigned long,
2210 unsigned long, unsigned long, unsigned long,
2211 unsigned long, unsigned long, unsigned long);
2214 if (!scanhex(&adrs
))
2218 for (i
= 0; i
< 8; ++i
)
2220 for (i
= 0; i
< 8; ++i
) {
2221 if (!scanhex(&args
[i
]) || termch
== '\n')
2225 func
= (callfunc_t
) adrs
;
2227 if (setjmp(bus_error_jmp
) == 0) {
2228 catch_memory_errors
= 1;
2230 ret
= func(args
[0], args
[1], args
[2], args
[3],
2231 args
[4], args
[5], args
[6], args
[7]);
2233 printf("return value is %x\n", ret
);
2235 printf("*** %x exception occurred\n", fault_except
);
2237 catch_memory_errors
= 0;
2240 /* Input scanning routines */
2251 while( c
== ' ' || c
== '\t' )
2257 static char *regnames
[N_PTREGS
] = {
2258 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
2259 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
2260 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
2261 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
2262 "pc", "msr", "or3", "ctr", "lr", "xer", "ccr",
2268 "trap", "dar", "dsisr", "res"
2272 scanhex(unsigned long *vp
)
2279 /* parse register name */
2283 for (i
= 0; i
< sizeof(regname
) - 1; ++i
) {
2292 for (i
= 0; i
< N_PTREGS
; ++i
) {
2293 if (strcmp(regnames
[i
], regname
) == 0) {
2294 if (xmon_regs
== NULL
) {
2295 printf("regs not available\n");
2298 *vp
= ((unsigned long *)xmon_regs
)[i
];
2302 printf("invalid register name '%%%s'\n", regname
);
2306 /* skip leading "0x" if any */
2320 } else if (c
== '$') {
2322 for (i
=0; i
<63; i
++) {
2332 if (setjmp(bus_error_jmp
) == 0) {
2333 catch_memory_errors
= 1;
2335 *vp
= kallsyms_lookup_name(tmpstr
);
2338 catch_memory_errors
= 0;
2340 printf("unknown symbol '%s'\n", tmpstr
);
2375 if( '0' <= c
&& c
<= '9' )
2377 if( 'A' <= c
&& c
<= 'F' )
2378 return c
- ('A' - 10);
2379 if( 'a' <= c
&& c
<= 'f' )
2380 return c
- ('a' - 10);
2385 getstring(char *s
, int size
)
2396 } while( c
!= ' ' && c
!= '\t' && c
!= '\n' );
2401 static char line
[256];
2402 static char *lineptr
;
2413 if (lineptr
== NULL
|| *lineptr
== 0) {
2414 if (xmon_gets(line
, sizeof(line
)) == NULL
) {
2424 take_input(char *str
)
2433 int type
= inchar();
2435 static char tmp
[64];
2440 xmon_print_symbol(addr
, ": ", "\n");
2445 if (setjmp(bus_error_jmp
) == 0) {
2446 catch_memory_errors
= 1;
2448 addr
= kallsyms_lookup_name(tmp
);
2450 printf("%s: %lx\n", tmp
, addr
);
2452 printf("Symbol '%s' not found.\n", tmp
);
2455 catch_memory_errors
= 0;
2462 /* Print an address in numeric and symbolic form (if possible) */
2463 static void xmon_print_symbol(unsigned long address
, const char *mid
,
2467 const char *name
= NULL
;
2468 unsigned long offset
, size
;
2470 printf(REG
, address
);
2471 if (setjmp(bus_error_jmp
) == 0) {
2472 catch_memory_errors
= 1;
2474 name
= kallsyms_lookup(address
, &size
, &offset
, &modname
,
2477 /* wait a little while to see if we get a machine check */
2481 catch_memory_errors
= 0;
2484 printf("%s%s+%#lx/%#lx", mid
, name
, offset
, size
);
2486 printf(" [%s]", modname
);
2488 printf("%s", after
);
2492 static void dump_slb(void)
2497 printf("SLB contents of cpu %x\n", smp_processor_id());
2499 for (i
= 0; i
< SLB_NUM_ENTRIES
; i
++) {
2500 asm volatile("slbmfee %0,%1" : "=r" (tmp
) : "r" (i
));
2501 printf("%02d %016lx ", i
, tmp
);
2503 asm volatile("slbmfev %0,%1" : "=r" (tmp
) : "r" (i
));
2504 printf("%016lx\n", tmp
);
2508 static void dump_stab(void)
2511 unsigned long *tmp
= (unsigned long *)get_paca()->stab_addr
;
2513 printf("Segment table contents of cpu %x\n", smp_processor_id());
2515 for (i
= 0; i
< PAGE_SIZE
/16; i
++) {
2522 printf("%03d %016lx ", i
, a
);
2523 printf("%016lx\n", b
);
2528 void dump_segments(void)
2530 if (cpu_has_feature(CPU_FTR_SLB
))
2537 #ifdef CONFIG_PPC_STD_MMU_32
2538 void dump_segments(void)
2543 for (i
= 0; i
< 16; ++i
)
2544 printf(" %x", mfsrin(i
));
2549 void xmon_init(int enable
)
2553 __debugger_ipi
= xmon_ipi
;
2554 __debugger_bpt
= xmon_bpt
;
2555 __debugger_sstep
= xmon_sstep
;
2556 __debugger_iabr_match
= xmon_iabr_match
;
2557 __debugger_dabr_match
= xmon_dabr_match
;
2558 __debugger_fault_handler
= xmon_fault_handler
;
2561 __debugger_ipi
= NULL
;
2562 __debugger_bpt
= NULL
;
2563 __debugger_sstep
= NULL
;
2564 __debugger_iabr_match
= NULL
;
2565 __debugger_dabr_match
= NULL
;
2566 __debugger_fault_handler
= NULL
;
2571 #ifdef CONFIG_MAGIC_SYSRQ
2572 static void sysrq_handle_xmon(int key
, struct pt_regs
*pt_regs
,
2573 struct tty_struct
*tty
)
2575 /* ensure xmon is enabled */
2580 static struct sysrq_key_op sysrq_xmon_op
=
2582 .handler
= sysrq_handle_xmon
,
2584 .action_msg
= "Entering xmon",
2587 static int __init
setup_xmon_sysrq(void)
2589 register_sysrq_key('x', &sysrq_xmon_op
);
2592 __initcall(setup_xmon_sysrq
);
2593 #endif /* CONFIG_MAGIC_SYSRQ */