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/errno.h>
12 #include <linux/sched.h>
13 #include <linux/smp.h>
15 #include <linux/reboot.h>
16 #include <linux/delay.h>
17 #include <linux/kallsyms.h>
18 #include <linux/cpumask.h>
19 #include <linux/module.h>
20 #include <linux/sysrq.h>
21 #include <linux/interrupt.h>
23 #include <asm/ptrace.h>
24 #include <asm/string.h>
26 #include <asm/machdep.h>
28 #include <asm/processor.h>
29 #include <asm/pgtable.h>
31 #include <asm/mmu_context.h>
32 #include <asm/cputable.h>
34 #include <asm/sstep.h>
38 #include <asm/hvcall.h>
44 #define scanhex xmon_scanhex
45 #define skipbl xmon_skipbl
48 cpumask_t cpus_in_xmon
= CPU_MASK_NONE
;
49 static unsigned long xmon_taken
= 1;
50 static int xmon_owner
;
52 #endif /* CONFIG_SMP */
54 static unsigned long in_xmon
= 0;
56 static unsigned long adrs
;
58 #define MAX_DUMP (128 * 1024)
59 static unsigned long ndump
= 64;
60 static unsigned long nidump
= 16;
61 static unsigned long ncsum
= 4096;
63 static char tmpstr
[128];
65 #define JMP_BUF_LEN 23
66 static long bus_error_jmp
[JMP_BUF_LEN
];
67 static int catch_memory_errors
;
68 static long *xmon_fault_jmp
[NR_CPUS
];
69 #define setjmp xmon_setjmp
70 #define longjmp xmon_longjmp
72 /* Breakpoint stuff */
74 unsigned long address
;
75 unsigned int instr
[2];
81 /* Bits in bpt.enabled */
82 #define BP_IABR_TE 1 /* IABR translation enabled */
88 static struct bpt bpts
[NBPTS
];
89 static struct bpt dabr
;
90 static struct bpt
*iabr
;
91 static unsigned bpinstr
= 0x7fe00008; /* trap */
93 #define BP_NUM(bp) ((bp) - bpts + 1)
96 static int cmds(struct pt_regs
*);
97 static int mread(unsigned long, void *, int);
98 static int mwrite(unsigned long, void *, int);
99 static int handle_fault(struct pt_regs
*);
100 static void byterev(unsigned char *, int);
101 static void memex(void);
102 static int bsesc(void);
103 static void dump(void);
104 static void prdump(unsigned long, long);
105 static int ppc_inst_dump(unsigned long, long, int);
106 void print_address(unsigned long);
107 static void backtrace(struct pt_regs
*);
108 static void excprint(struct pt_regs
*);
109 static void prregs(struct pt_regs
*);
110 static void memops(int);
111 static void memlocate(void);
112 static void memzcan(void);
113 static void memdiffs(unsigned char *, unsigned char *, unsigned, unsigned);
115 int scanhex(unsigned long *valp
);
116 static void scannl(void);
117 static int hexdigit(int);
118 void getstring(char *, int);
119 static void flush_input(void);
120 static int inchar(void);
121 static void take_input(char *);
122 static unsigned long read_spr(int);
123 static void write_spr(int, unsigned long);
124 static void super_regs(void);
125 static void remove_bpts(void);
126 static void insert_bpts(void);
127 static void remove_cpu_bpts(void);
128 static void insert_cpu_bpts(void);
129 static struct bpt
*at_breakpoint(unsigned long pc
);
130 static struct bpt
*in_breakpoint_table(unsigned long pc
, unsigned long *offp
);
131 static int do_step(struct pt_regs
*);
132 static void bpt_cmds(void);
133 static void cacheflush(void);
134 static int cpu_cmd(void);
135 static void csum(void);
136 static void bootcmds(void);
137 static void proccall(void);
138 void dump_segments(void);
139 static void symbol_lookup(void);
140 static void xmon_print_symbol(unsigned long address
, const char *mid
,
142 static const char *getvecname(unsigned long vec
);
144 extern int print_insn_powerpc(unsigned long, unsigned long, int);
146 extern void xmon_enter(void);
147 extern void xmon_leave(void);
149 extern long setjmp(long *);
150 extern void longjmp(long *, long);
151 extern void xmon_save_regs(struct pt_regs
*);
155 #define REGS_PER_LINE 4
156 #define LAST_VOLATILE 13
159 #define REGS_PER_LINE 8
160 #define LAST_VOLATILE 12
163 #define GETWORD(v) (((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
165 #define isxdigit(c) (('0' <= (c) && (c) <= '9') \
166 || ('a' <= (c) && (c) <= 'f') \
167 || ('A' <= (c) && (c) <= 'F'))
168 #define isalnum(c) (('0' <= (c) && (c) <= '9') \
169 || ('a' <= (c) && (c) <= 'z') \
170 || ('A' <= (c) && (c) <= 'Z'))
171 #define isspace(c) (c == ' ' || c == '\t' || c == 10 || c == 13 || c == 0)
173 static char *help_string
= "\
175 b show breakpoints\n\
176 bd set data breakpoint\n\
177 bi set instruction breakpoint\n\
178 bc clear breakpoint\n"
181 c print cpus stopped in xmon\n\
182 c# try to switch to cpu number h (in hex)\n"
187 di dump instructions\n\
188 df dump float values\n\
189 dd dump double values\n\
190 dr dump stream of raw bytes\n\
191 e print exception information\n\
193 la lookup symbol+offset of specified address\n\
194 ls lookup address of specified symbol\n\
195 m examine/change memory\n\
196 mm move a block of memory\n\
197 ms set a block of memory\n\
198 md compare two blocks of memory\n\
199 ml locate a block of memory\n\
200 mz zero a block of memory\n\
201 mi show information about memory allocation\n\
202 p call a procedure\n\
205 S print special registers\n\
207 x exit monitor and recover\n\
208 X exit monitor and dont recover\n"
210 " u dump segment table or SLB\n"
212 #ifdef CONFIG_PPC_STD_MMU_32
213 " u dump segment registers\n"
220 static struct pt_regs
*xmon_regs
;
222 static inline void sync(void)
224 asm volatile("sync; isync");
227 static inline void store_inst(void *p
)
229 asm volatile ("dcbst 0,%0; sync; icbi 0,%0; isync" : : "r" (p
));
232 static inline void cflush(void *p
)
234 asm volatile ("dcbf 0,%0; icbi 0,%0" : : "r" (p
));
237 static inline void cinval(void *p
)
239 asm volatile ("dcbi 0,%0; icbi 0,%0" : : "r" (p
));
243 * Disable surveillance (the service processor watchdog function)
244 * while we are in xmon.
245 * XXX we should re-enable it when we leave. :)
247 #define SURVEILLANCE_TOKEN 9000
249 static inline void disable_surveillance(void)
251 #ifdef CONFIG_PPC_PSERIES
252 /* Since this can't be a module, args should end up below 4GB. */
253 static struct rtas_args args
;
256 * At this point we have got all the cpus we can into
257 * xmon, so there is hopefully no other cpu calling RTAS
258 * at the moment, even though we don't take rtas.lock.
259 * If we did try to take rtas.lock there would be a
260 * real possibility of deadlock.
262 args
.token
= rtas_token("set-indicator");
263 if (args
.token
== RTAS_UNKNOWN_SERVICE
)
267 args
.rets
= &args
.args
[3];
268 args
.args
[0] = SURVEILLANCE_TOKEN
;
271 enter_rtas(__pa(&args
));
272 #endif /* CONFIG_PPC_PSERIES */
276 static int xmon_speaker
;
278 static void get_output_lock(void)
280 int me
= smp_processor_id() + 0x100;
281 int last_speaker
= 0, prev
;
284 if (xmon_speaker
== me
)
287 if (xmon_speaker
== 0) {
288 last_speaker
= cmpxchg(&xmon_speaker
, 0, me
);
289 if (last_speaker
== 0)
293 while (xmon_speaker
== last_speaker
) {
296 /* hostile takeover */
297 prev
= cmpxchg(&xmon_speaker
, last_speaker
, me
);
298 if (prev
== last_speaker
)
305 static void release_output_lock(void)
311 static int xmon_core(struct pt_regs
*regs
, int fromipi
)
316 long recurse_jmp
[JMP_BUF_LEN
];
317 unsigned long offset
;
321 unsigned long timeout
;
325 mtmsr(msr
& ~MSR_EE
); /* disable interrupts */
327 bp
= in_breakpoint_table(regs
->nip
, &offset
);
329 regs
->nip
= bp
->address
+ offset
;
330 atomic_dec(&bp
->ref_count
);
336 cpu
= smp_processor_id();
337 if (cpu_isset(cpu
, cpus_in_xmon
)) {
340 printf("cpu 0x%x: Exception %lx %s in xmon, "
341 "returning to main loop\n",
342 cpu
, regs
->trap
, getvecname(TRAP(regs
)));
343 release_output_lock();
344 longjmp(xmon_fault_jmp
[cpu
], 1);
347 if (setjmp(recurse_jmp
) != 0) {
348 if (!in_xmon
|| !xmon_gate
) {
350 printf("xmon: WARNING: bad recursive fault "
351 "on cpu 0x%x\n", cpu
);
352 release_output_lock();
355 secondary
= !(xmon_taken
&& cpu
== xmon_owner
);
359 xmon_fault_jmp
[cpu
] = recurse_jmp
;
360 cpu_set(cpu
, cpus_in_xmon
);
363 if ((regs
->msr
& (MSR_IR
|MSR_PR
|MSR_SF
)) == (MSR_IR
|MSR_SF
))
364 bp
= at_breakpoint(regs
->nip
);
365 if (bp
|| (regs
->msr
& MSR_RI
) == 0)
372 printf("cpu 0x%x stopped at breakpoint 0x%x (",
374 xmon_print_symbol(regs
->nip
, " ", ")\n");
376 if ((regs
->msr
& MSR_RI
) == 0)
377 printf("WARNING: exception is not recoverable, "
379 release_output_lock();
384 while (secondary
&& !xmon_gate
) {
388 secondary
= test_and_set_bit(0, &in_xmon
);
393 if (!secondary
&& !xmon_gate
) {
394 /* we are the first cpu to come in */
395 /* interrupt other cpu(s) */
396 int ncpus
= num_online_cpus();
401 smp_send_debugger_break(MSG_ALL_BUT_SELF
);
402 /* wait for other cpus to come in */
403 for (timeout
= 100000000; timeout
!= 0; --timeout
) {
404 if (cpus_weight(cpus_in_xmon
) >= ncpus
)
410 disable_surveillance();
411 /* for breakpoint or single step, print the current instr. */
412 if (bp
|| TRAP(regs
) == 0xd00)
413 ppc_inst_dump(regs
->nip
, 1, 0);
414 printf("enter ? for help\n");
423 if (cpu
== xmon_owner
) {
424 if (!test_and_set_bit(0, &xmon_taken
)) {
429 while (cpu
== xmon_owner
)
443 /* have switched to some other cpu */
448 cpu_clear(cpu
, cpus_in_xmon
);
449 xmon_fault_jmp
[cpu
] = NULL
;
451 /* UP is simple... */
453 printf("Exception %lx %s in xmon, returning to main loop\n",
454 regs
->trap
, getvecname(TRAP(regs
)));
455 longjmp(xmon_fault_jmp
[0], 1);
457 if (setjmp(recurse_jmp
) == 0) {
458 xmon_fault_jmp
[0] = recurse_jmp
;
462 bp
= at_breakpoint(regs
->nip
);
464 printf("Stopped at breakpoint %x (", BP_NUM(bp
));
465 xmon_print_symbol(regs
->nip
, " ", ")\n");
467 if ((regs
->msr
& MSR_RI
) == 0)
468 printf("WARNING: exception is not recoverable, "
471 disable_surveillance();
472 /* for breakpoint or single step, print the current instr. */
473 if (bp
|| TRAP(regs
) == 0xd00)
474 ppc_inst_dump(regs
->nip
, 1, 0);
475 printf("enter ? for help\n");
484 if ((regs
->msr
& (MSR_IR
|MSR_PR
|MSR_SF
)) == (MSR_IR
|MSR_SF
)) {
485 bp
= at_breakpoint(regs
->nip
);
487 int stepped
= emulate_step(regs
, bp
->instr
[0]);
489 regs
->nip
= (unsigned long) &bp
->instr
[0];
490 atomic_inc(&bp
->ref_count
);
491 } else if (stepped
< 0) {
492 printf("Couldn't single-step %s instruction\n",
493 (IS_RFID(bp
->instr
[0])? "rfid": "mtmsrd"));
500 mtmsr(msr
); /* restore interrupt enable */
505 int xmon(struct pt_regs
*excp
)
510 xmon_save_regs(®s
);
513 return xmon_core(excp
, 0);
518 xmon_irq(int irq
, void *d
, struct pt_regs
*regs
)
521 local_irq_save(flags
);
522 printf("Keyboard interrupt\n");
524 local_irq_restore(flags
);
528 static int xmon_bpt(struct pt_regs
*regs
)
531 unsigned long offset
;
533 if ((regs
->msr
& (MSR_IR
|MSR_PR
|MSR_SF
)) != (MSR_IR
|MSR_SF
))
536 /* Are we at the trap at bp->instr[1] for some bp? */
537 bp
= in_breakpoint_table(regs
->nip
, &offset
);
538 if (bp
!= NULL
&& offset
== 4) {
539 regs
->nip
= bp
->address
+ 4;
540 atomic_dec(&bp
->ref_count
);
544 /* Are we at a breakpoint? */
545 bp
= at_breakpoint(regs
->nip
);
554 static int xmon_sstep(struct pt_regs
*regs
)
562 static int xmon_dabr_match(struct pt_regs
*regs
)
564 if ((regs
->msr
& (MSR_IR
|MSR_PR
|MSR_SF
)) != (MSR_IR
|MSR_SF
))
566 if (dabr
.enabled
== 0)
572 static int xmon_iabr_match(struct pt_regs
*regs
)
574 if ((regs
->msr
& (MSR_IR
|MSR_PR
|MSR_SF
)) != (MSR_IR
|MSR_SF
))
582 static int xmon_ipi(struct pt_regs
*regs
)
585 if (in_xmon
&& !cpu_isset(smp_processor_id(), cpus_in_xmon
))
591 static int xmon_fault_handler(struct pt_regs
*regs
)
594 unsigned long offset
;
596 if (in_xmon
&& catch_memory_errors
)
597 handle_fault(regs
); /* doesn't return */
599 if ((regs
->msr
& (MSR_IR
|MSR_PR
|MSR_SF
)) == (MSR_IR
|MSR_SF
)) {
600 bp
= in_breakpoint_table(regs
->nip
, &offset
);
602 regs
->nip
= bp
->address
+ offset
;
603 atomic_dec(&bp
->ref_count
);
610 static struct bpt
*at_breakpoint(unsigned long pc
)
616 for (i
= 0; i
< NBPTS
; ++i
, ++bp
)
617 if (bp
->enabled
&& pc
== bp
->address
)
622 static struct bpt
*in_breakpoint_table(unsigned long nip
, unsigned long *offp
)
626 off
= nip
- (unsigned long) bpts
;
627 if (off
>= sizeof(bpts
))
629 off
%= sizeof(struct bpt
);
630 if (off
!= offsetof(struct bpt
, instr
[0])
631 && off
!= offsetof(struct bpt
, instr
[1]))
633 *offp
= off
- offsetof(struct bpt
, instr
[0]);
634 return (struct bpt
*) (nip
- off
);
637 static struct bpt
*new_breakpoint(unsigned long a
)
642 bp
= at_breakpoint(a
);
646 for (bp
= bpts
; bp
< &bpts
[NBPTS
]; ++bp
) {
647 if (!bp
->enabled
&& atomic_read(&bp
->ref_count
) == 0) {
649 bp
->instr
[1] = bpinstr
;
650 store_inst(&bp
->instr
[1]);
655 printf("Sorry, no free breakpoints. Please clear one first.\n");
659 static void insert_bpts(void)
665 for (i
= 0; i
< NBPTS
; ++i
, ++bp
) {
666 if ((bp
->enabled
& (BP_TRAP
|BP_IABR
)) == 0)
668 if (mread(bp
->address
, &bp
->instr
[0], 4) != 4) {
669 printf("Couldn't read instruction at %lx, "
670 "disabling breakpoint there\n", bp
->address
);
674 if (IS_MTMSRD(bp
->instr
[0]) || IS_RFID(bp
->instr
[0])) {
675 printf("Breakpoint at %lx is on an mtmsrd or rfid "
676 "instruction, disabling it\n", bp
->address
);
680 store_inst(&bp
->instr
[0]);
681 if (bp
->enabled
& BP_IABR
)
683 if (mwrite(bp
->address
, &bpinstr
, 4) != 4) {
684 printf("Couldn't write instruction at %lx, "
685 "disabling breakpoint there\n", bp
->address
);
686 bp
->enabled
&= ~BP_TRAP
;
689 store_inst((void *)bp
->address
);
693 static void insert_cpu_bpts(void)
696 set_dabr(dabr
.address
| (dabr
.enabled
& 7));
697 if (iabr
&& cpu_has_feature(CPU_FTR_IABR
))
698 mtspr(SPRN_IABR
, iabr
->address
699 | (iabr
->enabled
& (BP_IABR
|BP_IABR_TE
)));
702 static void remove_bpts(void)
709 for (i
= 0; i
< NBPTS
; ++i
, ++bp
) {
710 if ((bp
->enabled
& (BP_TRAP
|BP_IABR
)) != BP_TRAP
)
712 if (mread(bp
->address
, &instr
, 4) == 4
714 && mwrite(bp
->address
, &bp
->instr
, 4) != 4)
715 printf("Couldn't remove breakpoint at %lx\n",
718 store_inst((void *)bp
->address
);
722 static void remove_cpu_bpts(void)
725 if (cpu_has_feature(CPU_FTR_IABR
))
729 /* Command interpreting routine */
730 static char *last_cmd
;
733 cmds(struct pt_regs
*excp
)
741 printf("%x:", smp_processor_id());
742 #endif /* CONFIG_SMP */
748 if (last_cmd
== NULL
)
750 take_input(last_cmd
);
784 prregs(excp
); /* print regs */
806 printf(" <no input ...>\n");
828 #ifdef CONFIG_PPC_STD_MMU
834 printf("Unrecognized command: ");
836 if (' ' < cmd
&& cmd
<= '~')
839 printf("\\x%x", cmd
);
841 } while (cmd
!= '\n');
842 printf(" (type ? for help)\n");
849 * Step a single instruction.
850 * Some instructions we emulate, others we execute with MSR_SE set.
852 static int do_step(struct pt_regs
*regs
)
857 /* check we are in 64-bit kernel mode, translation enabled */
858 if ((regs
->msr
& (MSR_SF
|MSR_PR
|MSR_IR
)) == (MSR_SF
|MSR_IR
)) {
859 if (mread(regs
->nip
, &instr
, 4) == 4) {
860 stepped
= emulate_step(regs
, instr
);
862 printf("Couldn't single-step %s instruction\n",
863 (IS_RFID(instr
)? "rfid": "mtmsrd"));
867 regs
->trap
= 0xd00 | (regs
->trap
& 1);
868 printf("stepped to ");
869 xmon_print_symbol(regs
->nip
, " ", "\n");
870 ppc_inst_dump(regs
->nip
, 1, 0);
879 static void bootcmds(void)
885 ppc_md
.restart(NULL
);
892 static int cpu_cmd(void)
899 if (!scanhex(&cpu
)) {
900 /* print cpus waiting or in xmon */
901 printf("cpus stopped:");
903 for (cpu
= 0; cpu
< NR_CPUS
; ++cpu
) {
904 if (cpu_isset(cpu
, cpus_in_xmon
)) {
910 printf("-%x", cpu
- 1);
915 printf("-%x", NR_CPUS
- 1);
919 /* try to switch to cpu specified */
920 if (!cpu_isset(cpu
, cpus_in_xmon
)) {
921 printf("cpu 0x%x isn't in xmon\n", cpu
);
928 while (!xmon_taken
) {
929 if (--timeout
== 0) {
930 if (test_and_set_bit(0, &xmon_taken
))
932 /* take control back */
934 xmon_owner
= smp_processor_id();
935 printf("cpu %u didn't take control\n", cpu
);
943 #endif /* CONFIG_SMP */
946 static unsigned short fcstab
[256] = {
947 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
948 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
949 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
950 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
951 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
952 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
953 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
954 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
955 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
956 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
957 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
958 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
959 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
960 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
961 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
962 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
963 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
964 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
965 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
966 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
967 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
968 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
969 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
970 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
971 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
972 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
973 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
974 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
975 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
976 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
977 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
978 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
981 #define FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
992 if (!scanhex(&ncsum
))
995 for (i
= 0; i
< ncsum
; ++i
) {
996 if (mread(adrs
+i
, &v
, 1) == 0) {
997 printf("csum stopped at %x\n", adrs
+i
);
1002 printf("%x\n", fcs
);
1006 * Check if this is a suitable place to put a breakpoint.
1008 static long check_bp_loc(unsigned long addr
)
1013 if (!is_kernel_addr(addr
)) {
1014 printf("Breakpoints may only be placed at kernel addresses\n");
1017 if (!mread(addr
, &instr
, sizeof(instr
))) {
1018 printf("Can't read instruction at address %lx\n", addr
);
1021 if (IS_MTMSRD(instr
) || IS_RFID(instr
)) {
1022 printf("Breakpoints may not be placed on mtmsrd or rfid "
1029 static char *breakpoint_help_string
=
1030 "Breakpoint command usage:\n"
1031 "b show breakpoints\n"
1032 "b <addr> [cnt] set breakpoint at given instr addr\n"
1033 "bc clear all breakpoints\n"
1034 "bc <n/addr> clear breakpoint number n or at addr\n"
1035 "bi <addr> [cnt] set hardware instr breakpoint (POWER3/RS64 only)\n"
1036 "bd <addr> [cnt] set hardware data breakpoint\n"
1046 const char badaddr
[] = "Only kernel addresses are permitted "
1047 "for breakpoints\n";
1052 case 'd': /* bd - hardware data breakpoint */
1057 else if (cmd
== 'w')
1063 if (scanhex(&dabr
.address
)) {
1064 if (!is_kernel_addr(dabr
.address
)) {
1069 dabr
.enabled
= mode
| BP_DABR
;
1073 case 'i': /* bi - hardware instr breakpoint */
1074 if (!cpu_has_feature(CPU_FTR_IABR
)) {
1075 printf("Hardware instruction breakpoint "
1076 "not supported on this cpu\n");
1080 iabr
->enabled
&= ~(BP_IABR
| BP_IABR_TE
);
1085 if (!check_bp_loc(a
))
1087 bp
= new_breakpoint(a
);
1089 bp
->enabled
|= BP_IABR
| BP_IABR_TE
;
1097 /* clear all breakpoints */
1098 for (i
= 0; i
< NBPTS
; ++i
)
1099 bpts
[i
].enabled
= 0;
1102 printf("All breakpoints cleared\n");
1106 if (a
<= NBPTS
&& a
>= 1) {
1107 /* assume a breakpoint number */
1108 bp
= &bpts
[a
-1]; /* bp nums are 1 based */
1110 /* assume a breakpoint address */
1111 bp
= at_breakpoint(a
);
1113 printf("No breakpoint at %x\n", a
);
1118 printf("Cleared breakpoint %x (", BP_NUM(bp
));
1119 xmon_print_symbol(bp
->address
, " ", ")\n");
1127 printf(breakpoint_help_string
);
1132 /* print all breakpoints */
1133 printf(" type address\n");
1135 printf(" data "REG
" [", dabr
.address
);
1136 if (dabr
.enabled
& 1)
1138 if (dabr
.enabled
& 2)
1142 for (bp
= bpts
; bp
< &bpts
[NBPTS
]; ++bp
) {
1145 printf("%2x %s ", BP_NUM(bp
),
1146 (bp
->enabled
& BP_IABR
)? "inst": "trap");
1147 xmon_print_symbol(bp
->address
, " ", "\n");
1152 if (!check_bp_loc(a
))
1154 bp
= new_breakpoint(a
);
1156 bp
->enabled
|= BP_TRAP
;
1161 /* Very cheap human name for vector lookup. */
1163 const char *getvecname(unsigned long vec
)
1168 case 0x100: ret
= "(System Reset)"; break;
1169 case 0x200: ret
= "(Machine Check)"; break;
1170 case 0x300: ret
= "(Data Access)"; break;
1171 case 0x380: ret
= "(Data SLB Access)"; break;
1172 case 0x400: ret
= "(Instruction Access)"; break;
1173 case 0x480: ret
= "(Instruction SLB Access)"; break;
1174 case 0x500: ret
= "(Hardware Interrupt)"; break;
1175 case 0x600: ret
= "(Alignment)"; break;
1176 case 0x700: ret
= "(Program Check)"; break;
1177 case 0x800: ret
= "(FPU Unavailable)"; break;
1178 case 0x900: ret
= "(Decrementer)"; break;
1179 case 0xc00: ret
= "(System Call)"; break;
1180 case 0xd00: ret
= "(Single Step)"; break;
1181 case 0xf00: ret
= "(Performance Monitor)"; break;
1182 case 0xf20: ret
= "(Altivec Unavailable)"; break;
1183 case 0x1300: ret
= "(Instruction Breakpoint)"; break;
1189 static void get_function_bounds(unsigned long pc
, unsigned long *startp
,
1190 unsigned long *endp
)
1192 unsigned long size
, offset
;
1196 *startp
= *endp
= 0;
1199 if (setjmp(bus_error_jmp
) == 0) {
1200 catch_memory_errors
= 1;
1202 name
= kallsyms_lookup(pc
, &size
, &offset
, &modname
, tmpstr
);
1204 *startp
= pc
- offset
;
1205 *endp
= pc
- offset
+ size
;
1209 catch_memory_errors
= 0;
1212 static int xmon_depth_to_print
= 64;
1215 #define LRSAVE_OFFSET 0x10
1216 #define REG_FRAME_MARKER 0x7265677368657265ul /* "regshere" */
1217 #define MARKER_OFFSET 0x60
1218 #define REGS_OFFSET 0x70
1220 #define LRSAVE_OFFSET 4
1221 #define REG_FRAME_MARKER 0x72656773
1222 #define MARKER_OFFSET 8
1223 #define REGS_OFFSET 16
1226 static void xmon_show_stack(unsigned long sp
, unsigned long lr
,
1230 unsigned long newsp
;
1231 unsigned long marker
;
1233 struct pt_regs regs
;
1236 if (sp
< PAGE_OFFSET
) {
1238 printf("SP (%lx) is in userspace\n", sp
);
1242 if (!mread(sp
+ LRSAVE_OFFSET
, &ip
, sizeof(unsigned long))
1243 || !mread(sp
, &newsp
, sizeof(unsigned long))) {
1244 printf("Couldn't read stack frame at %lx\n", sp
);
1249 * For the first stack frame, try to work out if
1250 * LR and/or the saved LR value in the bottommost
1251 * stack frame are valid.
1253 if ((pc
| lr
) != 0) {
1254 unsigned long fnstart
, fnend
;
1255 unsigned long nextip
;
1258 get_function_bounds(pc
, &fnstart
, &fnend
);
1261 mread(newsp
+ LRSAVE_OFFSET
, &nextip
,
1262 sizeof(unsigned long));
1264 if (lr
< PAGE_OFFSET
1265 || (fnstart
<= lr
&& lr
< fnend
))
1267 } else if (lr
== nextip
) {
1269 } else if (lr
>= PAGE_OFFSET
1270 && !(fnstart
<= lr
&& lr
< fnend
)) {
1271 printf("[link register ] ");
1272 xmon_print_symbol(lr
, " ", "\n");
1275 printf("["REG
"] ", sp
);
1276 xmon_print_symbol(ip
, " ", " (unreliable)\n");
1281 printf("["REG
"] ", sp
);
1282 xmon_print_symbol(ip
, " ", "\n");
1285 /* Look for "regshere" marker to see if this is
1286 an exception frame. */
1287 if (mread(sp
+ MARKER_OFFSET
, &marker
, sizeof(unsigned long))
1288 && marker
== REG_FRAME_MARKER
) {
1289 if (mread(sp
+ REGS_OFFSET
, ®s
, sizeof(regs
))
1291 printf("Couldn't read registers at %lx\n",
1295 printf("--- Exception: %lx %s at ", regs
.trap
,
1296 getvecname(TRAP(®s
)));
1299 xmon_print_symbol(pc
, " ", "\n");
1306 } while (count
++ < xmon_depth_to_print
);
1309 static void backtrace(struct pt_regs
*excp
)
1314 xmon_show_stack(sp
, 0, 0);
1316 xmon_show_stack(excp
->gpr
[1], excp
->link
, excp
->nip
);
1320 static void print_bug_trap(struct pt_regs
*regs
)
1322 struct bug_entry
*bug
;
1325 if (regs
->msr
& MSR_PR
)
1326 return; /* not in kernel */
1327 addr
= regs
->nip
; /* address of trap instruction */
1328 if (addr
< PAGE_OFFSET
)
1330 bug
= find_bug(regs
->nip
);
1333 if (bug
->line
& BUG_WARNING_TRAP
)
1336 printf("kernel BUG in %s at %s:%d!\n",
1337 bug
->function
, bug
->file
, (unsigned int)bug
->line
);
1340 void excprint(struct pt_regs
*fp
)
1345 printf("cpu 0x%x: ", smp_processor_id());
1346 #endif /* CONFIG_SMP */
1349 printf("Vector: %lx %s at [%lx]\n", fp
->trap
, getvecname(trap
), fp
);
1351 xmon_print_symbol(fp
->nip
, ": ", "\n");
1353 printf(" lr: ", fp
->link
);
1354 xmon_print_symbol(fp
->link
, ": ", "\n");
1356 printf(" sp: %lx\n", fp
->gpr
[1]);
1357 printf(" msr: %lx\n", fp
->msr
);
1359 if (trap
== 0x300 || trap
== 0x380 || trap
== 0x600) {
1360 printf(" dar: %lx\n", fp
->dar
);
1362 printf(" dsisr: %lx\n", fp
->dsisr
);
1365 printf(" current = 0x%lx\n", current
);
1367 printf(" paca = 0x%lx\n", get_paca());
1370 printf(" pid = %ld, comm = %s\n",
1371 current
->pid
, current
->comm
);
1378 void prregs(struct pt_regs
*fp
)
1382 struct pt_regs regs
;
1384 if (scanhex(&base
)) {
1385 if (setjmp(bus_error_jmp
) == 0) {
1386 catch_memory_errors
= 1;
1388 regs
= *(struct pt_regs
*)base
;
1392 catch_memory_errors
= 0;
1393 printf("*** Error reading registers from "REG
"\n",
1397 catch_memory_errors
= 0;
1402 if (FULL_REGS(fp
)) {
1403 for (n
= 0; n
< 16; ++n
)
1404 printf("R%.2ld = "REG
" R%.2ld = "REG
"\n",
1405 n
, fp
->gpr
[n
], n
+16, fp
->gpr
[n
+16]);
1407 for (n
= 0; n
< 7; ++n
)
1408 printf("R%.2ld = "REG
" R%.2ld = "REG
"\n",
1409 n
, fp
->gpr
[n
], n
+7, fp
->gpr
[n
+7]);
1412 for (n
= 0; n
< 32; ++n
) {
1413 printf("R%.2d = %.8x%s", n
, fp
->gpr
[n
],
1414 (n
& 3) == 3? "\n": " ");
1415 if (n
== 12 && !FULL_REGS(fp
)) {
1422 xmon_print_symbol(fp
->nip
, " ", "\n");
1424 xmon_print_symbol(fp
->link
, " ", "\n");
1425 printf("msr = "REG
" cr = %.8lx\n", fp
->msr
, fp
->ccr
);
1426 printf("ctr = "REG
" xer = "REG
" trap = %4lx\n",
1427 fp
->ctr
, fp
->xer
, fp
->trap
);
1429 if (trap
== 0x300 || trap
== 0x380 || trap
== 0x600)
1430 printf("dar = "REG
" dsisr = %.8lx\n", fp
->dar
, fp
->dsisr
);
1433 void cacheflush(void)
1436 unsigned long nflush
;
1441 scanhex((void *)&adrs
);
1446 nflush
= (nflush
+ L1_CACHE_BYTES
- 1) / L1_CACHE_BYTES
;
1447 if (setjmp(bus_error_jmp
) == 0) {
1448 catch_memory_errors
= 1;
1452 for (; nflush
> 0; --nflush
, adrs
+= L1_CACHE_BYTES
)
1453 cflush((void *) adrs
);
1455 for (; nflush
> 0; --nflush
, adrs
+= L1_CACHE_BYTES
)
1456 cinval((void *) adrs
);
1459 /* wait a little while to see if we get a machine check */
1462 catch_memory_errors
= 0;
1468 unsigned int instrs
[2];
1469 unsigned long (*code
)(void);
1470 unsigned long ret
= -1UL;
1472 unsigned long opd
[3];
1474 opd
[0] = (unsigned long)instrs
;
1477 code
= (unsigned long (*)(void)) opd
;
1479 code
= (unsigned long (*)(void)) instrs
;
1482 /* mfspr r3,n; blr */
1483 instrs
[0] = 0x7c6002a6 + ((n
& 0x1F) << 16) + ((n
& 0x3e0) << 6);
1484 instrs
[1] = 0x4e800020;
1486 store_inst(instrs
+1);
1488 if (setjmp(bus_error_jmp
) == 0) {
1489 catch_memory_errors
= 1;
1495 /* wait a little while to see if we get a machine check */
1504 write_spr(int n
, unsigned long val
)
1506 unsigned int instrs
[2];
1507 unsigned long (*code
)(unsigned long);
1509 unsigned long opd
[3];
1511 opd
[0] = (unsigned long)instrs
;
1514 code
= (unsigned long (*)(unsigned long)) opd
;
1516 code
= (unsigned long (*)(unsigned long)) instrs
;
1519 instrs
[0] = 0x7c6003a6 + ((n
& 0x1F) << 16) + ((n
& 0x3e0) << 6);
1520 instrs
[1] = 0x4e800020;
1522 store_inst(instrs
+1);
1524 if (setjmp(bus_error_jmp
) == 0) {
1525 catch_memory_errors
= 1;
1531 /* wait a little while to see if we get a machine check */
1537 static unsigned long regno
;
1538 extern char exc_prolog
;
1539 extern char dec_exc
;
1541 void super_regs(void)
1545 #ifdef CONFIG_PPC_ISERIES
1546 struct paca_struct
*ptrPaca
= NULL
;
1547 struct lppaca
*ptrLpPaca
= NULL
;
1548 struct ItLpRegSave
*ptrLpRegSave
= NULL
;
1553 unsigned long sp
, toc
;
1554 asm("mr %0,1" : "=r" (sp
) :);
1555 asm("mr %0,2" : "=r" (toc
) :);
1557 printf("msr = "REG
" sprg0= "REG
"\n",
1558 mfmsr(), mfspr(SPRN_SPRG0
));
1559 printf("pvr = "REG
" sprg1= "REG
"\n",
1560 mfspr(SPRN_PVR
), mfspr(SPRN_SPRG1
));
1561 printf("dec = "REG
" sprg2= "REG
"\n",
1562 mfspr(SPRN_DEC
), mfspr(SPRN_SPRG2
));
1563 printf("sp = "REG
" sprg3= "REG
"\n", sp
, mfspr(SPRN_SPRG3
));
1564 printf("toc = "REG
" dar = "REG
"\n", toc
, mfspr(SPRN_DAR
));
1565 #ifdef CONFIG_PPC_ISERIES
1566 // Dump out relevant Paca data areas.
1568 ptrPaca
= get_paca();
1570 printf(" Local Processor Control Area (LpPaca): \n");
1571 ptrLpPaca
= ptrPaca
->lppaca_ptr
;
1572 printf(" Saved Srr0=%.16lx Saved Srr1=%.16lx \n",
1573 ptrLpPaca
->saved_srr0
, ptrLpPaca
->saved_srr1
);
1574 printf(" Saved Gpr3=%.16lx Saved Gpr4=%.16lx \n",
1575 ptrLpPaca
->saved_gpr3
, ptrLpPaca
->saved_gpr4
);
1576 printf(" Saved Gpr5=%.16lx \n", ptrLpPaca
->saved_gpr5
);
1578 printf(" Local Processor Register Save Area (LpRegSave): \n");
1579 ptrLpRegSave
= ptrPaca
->reg_save_ptr
;
1580 printf(" Saved Sprg0=%.16lx Saved Sprg1=%.16lx \n",
1581 ptrLpRegSave
->xSPRG0
, ptrLpRegSave
->xSPRG0
);
1582 printf(" Saved Sprg2=%.16lx Saved Sprg3=%.16lx \n",
1583 ptrLpRegSave
->xSPRG2
, ptrLpRegSave
->xSPRG3
);
1584 printf(" Saved Msr =%.16lx Saved Nia =%.16lx \n",
1585 ptrLpRegSave
->xMSR
, ptrLpRegSave
->xNIA
);
1594 val
= read_spr(regno
);
1596 write_spr(regno
, val
);
1599 printf("spr %lx = %lx\n", regno
, read_spr(regno
));
1606 * Stuff for reading and writing memory safely
1609 mread(unsigned long adrs
, void *buf
, int size
)
1615 if (setjmp(bus_error_jmp
) == 0) {
1616 catch_memory_errors
= 1;
1622 *(u16
*)q
= *(u16
*)p
;
1625 *(u32
*)q
= *(u32
*)p
;
1628 *(u64
*)q
= *(u64
*)p
;
1631 for( ; n
< size
; ++n
) {
1637 /* wait a little while to see if we get a machine check */
1641 catch_memory_errors
= 0;
1646 mwrite(unsigned long adrs
, void *buf
, int size
)
1652 if (setjmp(bus_error_jmp
) == 0) {
1653 catch_memory_errors
= 1;
1659 *(u16
*)p
= *(u16
*)q
;
1662 *(u32
*)p
= *(u32
*)q
;
1665 *(u64
*)p
= *(u64
*)q
;
1668 for ( ; n
< size
; ++n
) {
1674 /* wait a little while to see if we get a machine check */
1678 printf("*** Error writing address %x\n", adrs
+ n
);
1680 catch_memory_errors
= 0;
1684 static int fault_type
;
1685 static int fault_except
;
1686 static char *fault_chars
[] = { "--", "**", "##" };
1688 static int handle_fault(struct pt_regs
*regs
)
1690 fault_except
= TRAP(regs
);
1691 switch (TRAP(regs
)) {
1703 longjmp(bus_error_jmp
, 1);
1708 #define SWAP(a, b, t) ((t) = (a), (a) = (b), (b) = (t))
1711 byterev(unsigned char *val
, int size
)
1717 SWAP(val
[0], val
[1], t
);
1720 SWAP(val
[0], val
[3], t
);
1721 SWAP(val
[1], val
[2], t
);
1723 case 8: /* is there really any use for this? */
1724 SWAP(val
[0], val
[7], t
);
1725 SWAP(val
[1], val
[6], t
);
1726 SWAP(val
[2], val
[5], t
);
1727 SWAP(val
[3], val
[4], t
);
1735 static char *memex_help_string
=
1736 "Memory examine command usage:\n"
1737 "m [addr] [flags] examine/change memory\n"
1738 " addr is optional. will start where left off.\n"
1739 " flags may include chars from this set:\n"
1740 " b modify by bytes (default)\n"
1741 " w modify by words (2 byte)\n"
1742 " l modify by longs (4 byte)\n"
1743 " d modify by doubleword (8 byte)\n"
1744 " r toggle reverse byte order mode\n"
1745 " n do not read memory (for i/o spaces)\n"
1746 " . ok to read (default)\n"
1747 "NOTE: flags are saved as defaults\n"
1750 static char *memex_subcmd_help_string
=
1751 "Memory examine subcommands:\n"
1752 " hexval write this val to current location\n"
1753 " 'string' write chars from string to this location\n"
1754 " ' increment address\n"
1755 " ^ decrement address\n"
1756 " / increment addr by 0x10. //=0x100, ///=0x1000, etc\n"
1757 " \\ decrement addr by 0x10. \\\\=0x100, \\\\\\=0x1000, etc\n"
1758 " ` clear no-read flag\n"
1759 " ; stay at this addr\n"
1760 " v change to byte mode\n"
1761 " w change to word (2 byte) mode\n"
1762 " l change to long (4 byte) mode\n"
1763 " u change to doubleword (8 byte) mode\n"
1764 " m addr change current addr\n"
1765 " n toggle no-read flag\n"
1766 " r toggle byte reverse flag\n"
1767 " < count back up count bytes\n"
1768 " > count skip forward count bytes\n"
1769 " x exit this mode\n"
1775 int cmd
, inc
, i
, nslash
;
1777 unsigned char val
[16];
1779 scanhex((void *)&adrs
);
1782 printf(memex_help_string
);
1788 while ((cmd
= skipbl()) != '\n') {
1790 case 'b': size
= 1; break;
1791 case 'w': size
= 2; break;
1792 case 'l': size
= 4; break;
1793 case 'd': size
= 8; break;
1794 case 'r': brev
= !brev
; break;
1795 case 'n': mnoread
= 1; break;
1796 case '.': mnoread
= 0; break;
1805 n
= mread(adrs
, val
, size
);
1806 printf(REG
"%c", adrs
, brev
? 'r': ' ');
1811 for (i
= 0; i
< n
; ++i
)
1812 printf("%.2x", val
[i
]);
1813 for (; i
< size
; ++i
)
1814 printf("%s", fault_chars
[fault_type
]);
1821 for (i
= 0; i
< size
; ++i
)
1822 val
[i
] = n
>> (i
* 8);
1825 mwrite(adrs
, val
, size
);
1838 else if( n
== '\'' )
1840 for (i
= 0; i
< size
; ++i
)
1841 val
[i
] = n
>> (i
* 8);
1844 mwrite(adrs
, val
, size
);
1881 adrs
-= 1 << nslash
;
1885 adrs
+= 1 << nslash
;
1889 adrs
+= 1 << -nslash
;
1893 adrs
-= 1 << -nslash
;
1896 scanhex((void *)&adrs
);
1915 printf(memex_subcmd_help_string
);
1930 case 'n': c
= '\n'; break;
1931 case 'r': c
= '\r'; break;
1932 case 'b': c
= '\b'; break;
1933 case 't': c
= '\t'; break;
1938 static void xmon_rawdump (unsigned long adrs
, long ndump
)
1941 unsigned char temp
[16];
1943 for (n
= ndump
; n
> 0;) {
1945 nr
= mread(adrs
, temp
, r
);
1947 for (m
= 0; m
< r
; ++m
) {
1949 printf("%.2x", temp
[m
]);
1951 printf("%s", fault_chars
[fault_type
]);
1960 #define isxdigit(c) (('0' <= (c) && (c) <= '9') \
1961 || ('a' <= (c) && (c) <= 'f') \
1962 || ('A' <= (c) && (c) <= 'F'))
1969 if ((isxdigit(c
) && c
!= 'f' && c
!= 'd') || c
== '\n')
1971 scanhex((void *)&adrs
);
1978 else if (nidump
> MAX_DUMP
)
1980 adrs
+= ppc_inst_dump(adrs
, nidump
, 1);
1982 } else if (c
== 'r') {
1986 xmon_rawdump(adrs
, ndump
);
1993 else if (ndump
> MAX_DUMP
)
1995 prdump(adrs
, ndump
);
2002 prdump(unsigned long adrs
, long ndump
)
2004 long n
, m
, c
, r
, nr
;
2005 unsigned char temp
[16];
2007 for (n
= ndump
; n
> 0;) {
2011 nr
= mread(adrs
, temp
, r
);
2013 for (m
= 0; m
< r
; ++m
) {
2014 if ((m
& (sizeof(long) - 1)) == 0 && m
> 0)
2017 printf("%.2x", temp
[m
]);
2019 printf("%s", fault_chars
[fault_type
]);
2021 for (; m
< 16; ++m
) {
2022 if ((m
& (sizeof(long) - 1)) == 0)
2027 for (m
= 0; m
< r
; ++m
) {
2030 putchar(' ' <= c
&& c
<= '~'? c
: '.');
2044 ppc_inst_dump(unsigned long adr
, long count
, int praddr
)
2047 unsigned long first_adr
;
2048 unsigned long inst
, last_inst
= 0;
2049 unsigned char val
[4];
2052 for (first_adr
= adr
; count
> 0; --count
, adr
+= 4) {
2053 nr
= mread(adr
, val
, 4);
2056 const char *x
= fault_chars
[fault_type
];
2057 printf(REG
" %s%s%s%s\n", adr
, x
, x
, x
, x
);
2061 inst
= GETWORD(val
);
2062 if (adr
> first_adr
&& inst
== last_inst
) {
2072 printf(REG
" %.8x", adr
, inst
);
2074 print_insn_powerpc(inst
, adr
, 0); /* always returns 4 */
2077 return adr
- first_adr
;
2081 print_address(unsigned long addr
)
2083 xmon_print_symbol(addr
, "\t# ", "");
2088 * Memory operations - move, set, print differences
2090 static unsigned long mdest
; /* destination address */
2091 static unsigned long msrc
; /* source address */
2092 static unsigned long mval
; /* byte value to set memory to */
2093 static unsigned long mcount
; /* # bytes to affect */
2094 static unsigned long mdiffs
; /* max # differences to print */
2099 scanhex((void *)&mdest
);
2100 if( termch
!= '\n' )
2102 scanhex((void *)(cmd
== 's'? &mval
: &msrc
));
2103 if( termch
!= '\n' )
2105 scanhex((void *)&mcount
);
2108 memmove((void *)mdest
, (void *)msrc
, mcount
);
2111 memset((void *)mdest
, mval
, mcount
);
2114 if( termch
!= '\n' )
2116 scanhex((void *)&mdiffs
);
2117 memdiffs((unsigned char *)mdest
, (unsigned char *)msrc
, mcount
, mdiffs
);
2123 memdiffs(unsigned char *p1
, unsigned char *p2
, unsigned nb
, unsigned maxpr
)
2128 for( n
= nb
; n
> 0; --n
)
2129 if( *p1
++ != *p2
++ )
2130 if( ++prt
<= maxpr
)
2131 printf("%.16x %.2x # %.16x %.2x\n", p1
- 1,
2132 p1
[-1], p2
- 1, p2
[-1]);
2134 printf("Total of %d differences\n", prt
);
2137 static unsigned mend
;
2138 static unsigned mask
;
2144 unsigned char val
[4];
2147 scanhex((void *)&mdest
);
2148 if (termch
!= '\n') {
2150 scanhex((void *)&mend
);
2151 if (termch
!= '\n') {
2153 scanhex((void *)&mval
);
2155 if (termch
!= '\n') termch
= 0;
2156 scanhex((void *)&mask
);
2160 for (a
= mdest
; a
< mend
; a
+= 4) {
2161 if (mread(a
, val
, 4) == 4
2162 && ((GETWORD(val
) ^ mval
) & mask
) == 0) {
2163 printf("%.16x: %.16x\n", a
, GETWORD(val
));
2170 static unsigned long mskip
= 0x1000;
2171 static unsigned long mlim
= 0xffffffff;
2181 if (termch
!= '\n') termch
= 0;
2183 if (termch
!= '\n') termch
= 0;
2186 for (a
= mdest
; a
< mlim
; a
+= mskip
) {
2187 ok
= mread(a
, &v
, 1);
2189 printf("%.8x .. ", a
);
2190 } else if (!ok
&& ook
)
2191 printf("%.8x\n", a
- mskip
);
2197 printf("%.8x\n", a
- mskip
);
2202 unsigned long args
[8];
2205 typedef unsigned long (*callfunc_t
)(unsigned long, unsigned long,
2206 unsigned long, unsigned long, unsigned long,
2207 unsigned long, unsigned long, unsigned long);
2210 if (!scanhex(&adrs
))
2214 for (i
= 0; i
< 8; ++i
)
2216 for (i
= 0; i
< 8; ++i
) {
2217 if (!scanhex(&args
[i
]) || termch
== '\n')
2221 func
= (callfunc_t
) adrs
;
2223 if (setjmp(bus_error_jmp
) == 0) {
2224 catch_memory_errors
= 1;
2226 ret
= func(args
[0], args
[1], args
[2], args
[3],
2227 args
[4], args
[5], args
[6], args
[7]);
2229 printf("return value is %x\n", ret
);
2231 printf("*** %x exception occurred\n", fault_except
);
2233 catch_memory_errors
= 0;
2236 /* Input scanning routines */
2247 while( c
== ' ' || c
== '\t' )
2253 static char *regnames
[N_PTREGS
] = {
2254 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
2255 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
2256 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
2257 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
2258 "pc", "msr", "or3", "ctr", "lr", "xer", "ccr",
2264 "trap", "dar", "dsisr", "res"
2268 scanhex(unsigned long *vp
)
2275 /* parse register name */
2279 for (i
= 0; i
< sizeof(regname
) - 1; ++i
) {
2288 for (i
= 0; i
< N_PTREGS
; ++i
) {
2289 if (strcmp(regnames
[i
], regname
) == 0) {
2290 if (xmon_regs
== NULL
) {
2291 printf("regs not available\n");
2294 *vp
= ((unsigned long *)xmon_regs
)[i
];
2298 printf("invalid register name '%%%s'\n", regname
);
2302 /* skip leading "0x" if any */
2316 } else if (c
== '$') {
2318 for (i
=0; i
<63; i
++) {
2328 if (setjmp(bus_error_jmp
) == 0) {
2329 catch_memory_errors
= 1;
2331 *vp
= kallsyms_lookup_name(tmpstr
);
2334 catch_memory_errors
= 0;
2336 printf("unknown symbol '%s'\n", tmpstr
);
2371 if( '0' <= c
&& c
<= '9' )
2373 if( 'A' <= c
&& c
<= 'F' )
2374 return c
- ('A' - 10);
2375 if( 'a' <= c
&& c
<= 'f' )
2376 return c
- ('a' - 10);
2381 getstring(char *s
, int size
)
2392 } while( c
!= ' ' && c
!= '\t' && c
!= '\n' );
2397 static char line
[256];
2398 static char *lineptr
;
2409 if (lineptr
== NULL
|| *lineptr
== 0) {
2410 if (xmon_gets(line
, sizeof(line
)) == NULL
) {
2420 take_input(char *str
)
2429 int type
= inchar();
2431 static char tmp
[64];
2436 xmon_print_symbol(addr
, ": ", "\n");
2441 if (setjmp(bus_error_jmp
) == 0) {
2442 catch_memory_errors
= 1;
2444 addr
= kallsyms_lookup_name(tmp
);
2446 printf("%s: %lx\n", tmp
, addr
);
2448 printf("Symbol '%s' not found.\n", tmp
);
2451 catch_memory_errors
= 0;
2458 /* Print an address in numeric and symbolic form (if possible) */
2459 static void xmon_print_symbol(unsigned long address
, const char *mid
,
2463 const char *name
= NULL
;
2464 unsigned long offset
, size
;
2466 printf(REG
, address
);
2467 if (setjmp(bus_error_jmp
) == 0) {
2468 catch_memory_errors
= 1;
2470 name
= kallsyms_lookup(address
, &size
, &offset
, &modname
,
2473 /* wait a little while to see if we get a machine check */
2477 catch_memory_errors
= 0;
2480 printf("%s%s+%#lx/%#lx", mid
, name
, offset
, size
);
2482 printf(" [%s]", modname
);
2484 printf("%s", after
);
2488 static void dump_slb(void)
2493 printf("SLB contents of cpu %x\n", smp_processor_id());
2495 for (i
= 0; i
< SLB_NUM_ENTRIES
; i
++) {
2496 asm volatile("slbmfee %0,%1" : "=r" (tmp
) : "r" (i
));
2497 printf("%02d %016lx ", i
, tmp
);
2499 asm volatile("slbmfev %0,%1" : "=r" (tmp
) : "r" (i
));
2500 printf("%016lx\n", tmp
);
2504 static void dump_stab(void)
2507 unsigned long *tmp
= (unsigned long *)get_paca()->stab_addr
;
2509 printf("Segment table contents of cpu %x\n", smp_processor_id());
2511 for (i
= 0; i
< PAGE_SIZE
/16; i
++) {
2518 printf("%03d %016lx ", i
, a
);
2519 printf("%016lx\n", b
);
2524 void dump_segments(void)
2526 if (cpu_has_feature(CPU_FTR_SLB
))
2533 #ifdef CONFIG_PPC_STD_MMU_32
2534 void dump_segments(void)
2539 for (i
= 0; i
< 16; ++i
)
2540 printf(" %x", mfsrin(i
));
2545 void xmon_init(int enable
)
2549 __debugger_ipi
= xmon_ipi
;
2550 __debugger_bpt
= xmon_bpt
;
2551 __debugger_sstep
= xmon_sstep
;
2552 __debugger_iabr_match
= xmon_iabr_match
;
2553 __debugger_dabr_match
= xmon_dabr_match
;
2554 __debugger_fault_handler
= xmon_fault_handler
;
2557 __debugger_ipi
= NULL
;
2558 __debugger_bpt
= NULL
;
2559 __debugger_sstep
= NULL
;
2560 __debugger_iabr_match
= NULL
;
2561 __debugger_dabr_match
= NULL
;
2562 __debugger_fault_handler
= NULL
;
2567 #ifdef CONFIG_MAGIC_SYSRQ
2568 static void sysrq_handle_xmon(int key
, struct pt_regs
*pt_regs
,
2569 struct tty_struct
*tty
)
2571 /* ensure xmon is enabled */
2576 static struct sysrq_key_op sysrq_xmon_op
=
2578 .handler
= sysrq_handle_xmon
,
2580 .action_msg
= "Entering xmon",
2583 static int __init
setup_xmon_sysrq(void)
2585 register_sysrq_key('x', &sysrq_xmon_op
);
2588 __initcall(setup_xmon_sysrq
);
2589 #endif /* CONFIG_MAGIC_SYSRQ */