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 e print exception information\n\
196 la lookup symbol+offset of specified address\n\
197 ls lookup address of specified symbol\n\
198 m examine/change memory\n\
199 mm move a block of memory\n\
200 ms set a block of memory\n\
201 md compare two blocks of memory\n\
202 ml locate a block of memory\n\
203 mz zero a block of memory\n\
204 mi show information about memory allocation\n\
205 p call a procedure\n\
208 S print special registers\n\
210 x exit monitor and recover\n\
211 X exit monitor and dont recover\n"
213 " u dump segment table or SLB\n"
215 #ifdef CONFIG_PPC_STD_MMU_32
216 " u dump segment registers\n"
223 static struct pt_regs
*xmon_regs
;
225 static inline void sync(void)
227 asm volatile("sync; isync");
230 static inline void store_inst(void *p
)
232 asm volatile ("dcbst 0,%0; sync; icbi 0,%0; isync" : : "r" (p
));
235 static inline void cflush(void *p
)
237 asm volatile ("dcbf 0,%0; icbi 0,%0" : : "r" (p
));
240 static inline void cinval(void *p
)
242 asm volatile ("dcbi 0,%0; icbi 0,%0" : : "r" (p
));
246 * Disable surveillance (the service processor watchdog function)
247 * while we are in xmon.
248 * XXX we should re-enable it when we leave. :)
250 #define SURVEILLANCE_TOKEN 9000
252 static inline void disable_surveillance(void)
254 #ifdef CONFIG_PPC_PSERIES
255 /* Since this can't be a module, args should end up below 4GB. */
256 static struct rtas_args args
;
259 * At this point we have got all the cpus we can into
260 * xmon, so there is hopefully no other cpu calling RTAS
261 * at the moment, even though we don't take rtas.lock.
262 * If we did try to take rtas.lock there would be a
263 * real possibility of deadlock.
265 args
.token
= rtas_token("set-indicator");
266 if (args
.token
== RTAS_UNKNOWN_SERVICE
)
270 args
.rets
= &args
.args
[3];
271 args
.args
[0] = SURVEILLANCE_TOKEN
;
274 enter_rtas(__pa(&args
));
275 #endif /* CONFIG_PPC_PSERIES */
279 static int xmon_speaker
;
281 static void get_output_lock(void)
283 int me
= smp_processor_id() + 0x100;
284 int last_speaker
= 0, prev
;
287 if (xmon_speaker
== me
)
290 if (xmon_speaker
== 0) {
291 last_speaker
= cmpxchg(&xmon_speaker
, 0, me
);
292 if (last_speaker
== 0)
296 while (xmon_speaker
== last_speaker
) {
299 /* hostile takeover */
300 prev
= cmpxchg(&xmon_speaker
, last_speaker
, me
);
301 if (prev
== last_speaker
)
308 static void release_output_lock(void)
314 int xmon_core(struct pt_regs
*regs
, int fromipi
)
319 long recurse_jmp
[JMP_BUF_LEN
];
320 unsigned long offset
;
324 unsigned long timeout
;
328 mtmsr(msr
& ~MSR_EE
); /* disable interrupts */
330 bp
= in_breakpoint_table(regs
->nip
, &offset
);
332 regs
->nip
= bp
->address
+ offset
;
333 atomic_dec(&bp
->ref_count
);
339 cpu
= smp_processor_id();
340 if (cpu_isset(cpu
, cpus_in_xmon
)) {
343 printf("cpu 0x%x: Exception %lx %s in xmon, "
344 "returning to main loop\n",
345 cpu
, regs
->trap
, getvecname(TRAP(regs
)));
346 release_output_lock();
347 longjmp(xmon_fault_jmp
[cpu
], 1);
350 if (setjmp(recurse_jmp
) != 0) {
351 if (!in_xmon
|| !xmon_gate
) {
353 printf("xmon: WARNING: bad recursive fault "
354 "on cpu 0x%x\n", cpu
);
355 release_output_lock();
358 secondary
= !(xmon_taken
&& cpu
== xmon_owner
);
362 xmon_fault_jmp
[cpu
] = recurse_jmp
;
363 cpu_set(cpu
, cpus_in_xmon
);
366 if ((regs
->msr
& (MSR_IR
|MSR_PR
|MSR_SF
)) == (MSR_IR
|MSR_SF
))
367 bp
= at_breakpoint(regs
->nip
);
368 if (bp
|| (regs
->msr
& MSR_RI
) == 0)
375 printf("cpu 0x%x stopped at breakpoint 0x%x (",
377 xmon_print_symbol(regs
->nip
, " ", ")\n");
379 if ((regs
->msr
& MSR_RI
) == 0)
380 printf("WARNING: exception is not recoverable, "
382 release_output_lock();
387 while (secondary
&& !xmon_gate
) {
391 secondary
= test_and_set_bit(0, &in_xmon
);
396 if (!secondary
&& !xmon_gate
) {
397 /* we are the first cpu to come in */
398 /* interrupt other cpu(s) */
399 int ncpus
= num_online_cpus();
404 smp_send_debugger_break(MSG_ALL_BUT_SELF
);
405 /* wait for other cpus to come in */
406 for (timeout
= 100000000; timeout
!= 0; --timeout
) {
407 if (cpus_weight(cpus_in_xmon
) >= ncpus
)
413 disable_surveillance();
414 /* for breakpoint or single step, print the current instr. */
415 if (bp
|| TRAP(regs
) == 0xd00)
416 ppc_inst_dump(regs
->nip
, 1, 0);
417 printf("enter ? for help\n");
426 if (cpu
== xmon_owner
) {
427 if (!test_and_set_bit(0, &xmon_taken
)) {
432 while (cpu
== xmon_owner
)
446 /* have switched to some other cpu */
451 cpu_clear(cpu
, cpus_in_xmon
);
452 xmon_fault_jmp
[cpu
] = NULL
;
454 /* UP is simple... */
456 printf("Exception %lx %s in xmon, returning to main loop\n",
457 regs
->trap
, getvecname(TRAP(regs
)));
458 longjmp(xmon_fault_jmp
[0], 1);
460 if (setjmp(recurse_jmp
) == 0) {
461 xmon_fault_jmp
[0] = recurse_jmp
;
465 bp
= at_breakpoint(regs
->nip
);
467 printf("Stopped at breakpoint %x (", BP_NUM(bp
));
468 xmon_print_symbol(regs
->nip
, " ", ")\n");
470 if ((regs
->msr
& MSR_RI
) == 0)
471 printf("WARNING: exception is not recoverable, "
474 disable_surveillance();
475 /* for breakpoint or single step, print the current instr. */
476 if (bp
|| TRAP(regs
) == 0xd00)
477 ppc_inst_dump(regs
->nip
, 1, 0);
478 printf("enter ? for help\n");
487 if ((regs
->msr
& (MSR_IR
|MSR_PR
|MSR_SF
)) == (MSR_IR
|MSR_SF
)) {
488 bp
= at_breakpoint(regs
->nip
);
490 int stepped
= emulate_step(regs
, bp
->instr
[0]);
492 regs
->nip
= (unsigned long) &bp
->instr
[0];
493 atomic_inc(&bp
->ref_count
);
494 } else if (stepped
< 0) {
495 printf("Couldn't single-step %s instruction\n",
496 (IS_RFID(bp
->instr
[0])? "rfid": "mtmsrd"));
503 mtmsr(msr
); /* restore interrupt enable */
508 int xmon(struct pt_regs
*excp
)
513 xmon_save_regs(®s
);
516 return xmon_core(excp
, 0);
521 xmon_irq(int irq
, void *d
, struct pt_regs
*regs
)
524 local_irq_save(flags
);
525 printf("Keyboard interrupt\n");
527 local_irq_restore(flags
);
531 int xmon_bpt(struct pt_regs
*regs
)
534 unsigned long offset
;
536 if ((regs
->msr
& (MSR_IR
|MSR_PR
|MSR_SF
)) != (MSR_IR
|MSR_SF
))
539 /* Are we at the trap at bp->instr[1] for some bp? */
540 bp
= in_breakpoint_table(regs
->nip
, &offset
);
541 if (bp
!= NULL
&& offset
== 4) {
542 regs
->nip
= bp
->address
+ 4;
543 atomic_dec(&bp
->ref_count
);
547 /* Are we at a breakpoint? */
548 bp
= at_breakpoint(regs
->nip
);
557 int xmon_sstep(struct pt_regs
*regs
)
565 int xmon_dabr_match(struct pt_regs
*regs
)
567 if ((regs
->msr
& (MSR_IR
|MSR_PR
|MSR_SF
)) != (MSR_IR
|MSR_SF
))
569 if (dabr
.enabled
== 0)
575 int xmon_iabr_match(struct pt_regs
*regs
)
577 if ((regs
->msr
& (MSR_IR
|MSR_PR
|MSR_SF
)) != (MSR_IR
|MSR_SF
))
585 int xmon_ipi(struct pt_regs
*regs
)
588 if (in_xmon
&& !cpu_isset(smp_processor_id(), cpus_in_xmon
))
594 int xmon_fault_handler(struct pt_regs
*regs
)
597 unsigned long offset
;
599 if (in_xmon
&& catch_memory_errors
)
600 handle_fault(regs
); /* doesn't return */
602 if ((regs
->msr
& (MSR_IR
|MSR_PR
|MSR_SF
)) == (MSR_IR
|MSR_SF
)) {
603 bp
= in_breakpoint_table(regs
->nip
, &offset
);
605 regs
->nip
= bp
->address
+ offset
;
606 atomic_dec(&bp
->ref_count
);
613 static struct bpt
*at_breakpoint(unsigned long pc
)
619 for (i
= 0; i
< NBPTS
; ++i
, ++bp
)
620 if (bp
->enabled
&& pc
== bp
->address
)
625 static struct bpt
*in_breakpoint_table(unsigned long nip
, unsigned long *offp
)
629 off
= nip
- (unsigned long) bpts
;
630 if (off
>= sizeof(bpts
))
632 off
%= sizeof(struct bpt
);
633 if (off
!= offsetof(struct bpt
, instr
[0])
634 && off
!= offsetof(struct bpt
, instr
[1]))
636 *offp
= off
- offsetof(struct bpt
, instr
[0]);
637 return (struct bpt
*) (nip
- off
);
640 static struct bpt
*new_breakpoint(unsigned long a
)
645 bp
= at_breakpoint(a
);
649 for (bp
= bpts
; bp
< &bpts
[NBPTS
]; ++bp
) {
650 if (!bp
->enabled
&& atomic_read(&bp
->ref_count
) == 0) {
652 bp
->instr
[1] = bpinstr
;
653 store_inst(&bp
->instr
[1]);
658 printf("Sorry, no free breakpoints. Please clear one first.\n");
662 static void insert_bpts(void)
668 for (i
= 0; i
< NBPTS
; ++i
, ++bp
) {
669 if ((bp
->enabled
& (BP_TRAP
|BP_IABR
)) == 0)
671 if (mread(bp
->address
, &bp
->instr
[0], 4) != 4) {
672 printf("Couldn't read instruction at %lx, "
673 "disabling breakpoint there\n", bp
->address
);
677 if (IS_MTMSRD(bp
->instr
[0]) || IS_RFID(bp
->instr
[0])) {
678 printf("Breakpoint at %lx is on an mtmsrd or rfid "
679 "instruction, disabling it\n", bp
->address
);
683 store_inst(&bp
->instr
[0]);
684 if (bp
->enabled
& BP_IABR
)
686 if (mwrite(bp
->address
, &bpinstr
, 4) != 4) {
687 printf("Couldn't write instruction at %lx, "
688 "disabling breakpoint there\n", bp
->address
);
689 bp
->enabled
&= ~BP_TRAP
;
692 store_inst((void *)bp
->address
);
696 static void insert_cpu_bpts(void)
699 set_dabr(dabr
.address
| (dabr
.enabled
& 7));
700 if (iabr
&& cpu_has_feature(CPU_FTR_IABR
))
701 mtspr(SPRN_IABR
, iabr
->address
702 | (iabr
->enabled
& (BP_IABR
|BP_IABR_TE
)));
705 static void remove_bpts(void)
712 for (i
= 0; i
< NBPTS
; ++i
, ++bp
) {
713 if ((bp
->enabled
& (BP_TRAP
|BP_IABR
)) != BP_TRAP
)
715 if (mread(bp
->address
, &instr
, 4) == 4
717 && mwrite(bp
->address
, &bp
->instr
, 4) != 4)
718 printf("Couldn't remove breakpoint at %lx\n",
721 store_inst((void *)bp
->address
);
725 static void remove_cpu_bpts(void)
728 if (cpu_has_feature(CPU_FTR_IABR
))
732 /* Command interpreting routine */
733 static char *last_cmd
;
736 cmds(struct pt_regs
*excp
)
744 printf("%x:", smp_processor_id());
745 #endif /* CONFIG_SMP */
751 if (last_cmd
== NULL
)
753 take_input(last_cmd
);
787 prregs(excp
); /* print regs */
809 printf(" <no input ...>\n");
831 #ifdef CONFIG_PPC_STD_MMU
837 printf("Unrecognized command: ");
839 if (' ' < cmd
&& cmd
<= '~')
842 printf("\\x%x", cmd
);
844 } while (cmd
!= '\n');
845 printf(" (type ? for help)\n");
852 * Step a single instruction.
853 * Some instructions we emulate, others we execute with MSR_SE set.
855 static int do_step(struct pt_regs
*regs
)
860 /* check we are in 64-bit kernel mode, translation enabled */
861 if ((regs
->msr
& (MSR_SF
|MSR_PR
|MSR_IR
)) == (MSR_SF
|MSR_IR
)) {
862 if (mread(regs
->nip
, &instr
, 4) == 4) {
863 stepped
= emulate_step(regs
, instr
);
865 printf("Couldn't single-step %s instruction\n",
866 (IS_RFID(instr
)? "rfid": "mtmsrd"));
870 regs
->trap
= 0xd00 | (regs
->trap
& 1);
871 printf("stepped to ");
872 xmon_print_symbol(regs
->nip
, " ", "\n");
873 ppc_inst_dump(regs
->nip
, 1, 0);
882 static void bootcmds(void)
888 ppc_md
.restart(NULL
);
895 static int cpu_cmd(void)
902 if (!scanhex(&cpu
)) {
903 /* print cpus waiting or in xmon */
904 printf("cpus stopped:");
906 for (cpu
= 0; cpu
< NR_CPUS
; ++cpu
) {
907 if (cpu_isset(cpu
, cpus_in_xmon
)) {
913 printf("-%x", cpu
- 1);
918 printf("-%x", NR_CPUS
- 1);
922 /* try to switch to cpu specified */
923 if (!cpu_isset(cpu
, cpus_in_xmon
)) {
924 printf("cpu 0x%x isn't in xmon\n", cpu
);
931 while (!xmon_taken
) {
932 if (--timeout
== 0) {
933 if (test_and_set_bit(0, &xmon_taken
))
935 /* take control back */
937 xmon_owner
= smp_processor_id();
938 printf("cpu %u didn't take control\n", cpu
);
946 #endif /* CONFIG_SMP */
949 static unsigned short fcstab
[256] = {
950 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
951 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
952 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
953 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
954 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
955 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
956 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
957 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
958 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
959 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
960 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
961 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
962 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
963 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
964 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
965 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
966 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
967 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
968 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
969 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
970 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
971 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
972 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
973 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
974 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
975 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
976 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
977 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
978 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
979 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
980 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
981 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
984 #define FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
995 if (!scanhex(&ncsum
))
998 for (i
= 0; i
< ncsum
; ++i
) {
999 if (mread(adrs
+i
, &v
, 1) == 0) {
1000 printf("csum stopped at %x\n", adrs
+i
);
1005 printf("%x\n", fcs
);
1009 * Check if this is a suitable place to put a breakpoint.
1011 static long check_bp_loc(unsigned long addr
)
1016 if (addr
< KERNELBASE
) {
1017 printf("Breakpoints may only be placed at kernel addresses\n");
1020 if (!mread(addr
, &instr
, sizeof(instr
))) {
1021 printf("Can't read instruction at address %lx\n", addr
);
1024 if (IS_MTMSRD(instr
) || IS_RFID(instr
)) {
1025 printf("Breakpoints may not be placed on mtmsrd or rfid "
1032 static char *breakpoint_help_string
=
1033 "Breakpoint command usage:\n"
1034 "b show breakpoints\n"
1035 "b <addr> [cnt] set breakpoint at given instr addr\n"
1036 "bc clear all breakpoints\n"
1037 "bc <n/addr> clear breakpoint number n or at addr\n"
1038 "bi <addr> [cnt] set hardware instr breakpoint (POWER3/RS64 only)\n"
1039 "bd <addr> [cnt] set hardware data breakpoint\n"
1049 const char badaddr
[] = "Only kernel addresses are permitted "
1050 "for breakpoints\n";
1055 case 'd': /* bd - hardware data breakpoint */
1060 else if (cmd
== 'w')
1066 if (scanhex(&dabr
.address
)) {
1067 if (dabr
.address
< KERNELBASE
) {
1072 dabr
.enabled
= mode
| BP_DABR
;
1076 case 'i': /* bi - hardware instr breakpoint */
1077 if (!cpu_has_feature(CPU_FTR_IABR
)) {
1078 printf("Hardware instruction breakpoint "
1079 "not supported on this cpu\n");
1083 iabr
->enabled
&= ~(BP_IABR
| BP_IABR_TE
);
1088 if (!check_bp_loc(a
))
1090 bp
= new_breakpoint(a
);
1092 bp
->enabled
|= BP_IABR
| BP_IABR_TE
;
1100 /* clear all breakpoints */
1101 for (i
= 0; i
< NBPTS
; ++i
)
1102 bpts
[i
].enabled
= 0;
1105 printf("All breakpoints cleared\n");
1109 if (a
<= NBPTS
&& a
>= 1) {
1110 /* assume a breakpoint number */
1111 bp
= &bpts
[a
-1]; /* bp nums are 1 based */
1113 /* assume a breakpoint address */
1114 bp
= at_breakpoint(a
);
1116 printf("No breakpoint at %x\n", a
);
1121 printf("Cleared breakpoint %x (", BP_NUM(bp
));
1122 xmon_print_symbol(bp
->address
, " ", ")\n");
1130 printf(breakpoint_help_string
);
1135 /* print all breakpoints */
1136 printf(" type address\n");
1138 printf(" data "REG
" [", dabr
.address
);
1139 if (dabr
.enabled
& 1)
1141 if (dabr
.enabled
& 2)
1145 for (bp
= bpts
; bp
< &bpts
[NBPTS
]; ++bp
) {
1148 printf("%2x %s ", BP_NUM(bp
),
1149 (bp
->enabled
& BP_IABR
)? "inst": "trap");
1150 xmon_print_symbol(bp
->address
, " ", "\n");
1155 if (!check_bp_loc(a
))
1157 bp
= new_breakpoint(a
);
1159 bp
->enabled
|= BP_TRAP
;
1164 /* Very cheap human name for vector lookup. */
1166 const char *getvecname(unsigned long vec
)
1171 case 0x100: ret
= "(System Reset)"; break;
1172 case 0x200: ret
= "(Machine Check)"; break;
1173 case 0x300: ret
= "(Data Access)"; break;
1174 case 0x380: ret
= "(Data SLB Access)"; break;
1175 case 0x400: ret
= "(Instruction Access)"; break;
1176 case 0x480: ret
= "(Instruction SLB Access)"; break;
1177 case 0x500: ret
= "(Hardware Interrupt)"; break;
1178 case 0x600: ret
= "(Alignment)"; break;
1179 case 0x700: ret
= "(Program Check)"; break;
1180 case 0x800: ret
= "(FPU Unavailable)"; break;
1181 case 0x900: ret
= "(Decrementer)"; break;
1182 case 0xc00: ret
= "(System Call)"; break;
1183 case 0xd00: ret
= "(Single Step)"; break;
1184 case 0xf00: ret
= "(Performance Monitor)"; break;
1185 case 0xf20: ret
= "(Altivec Unavailable)"; break;
1186 case 0x1300: ret
= "(Instruction Breakpoint)"; break;
1192 static void get_function_bounds(unsigned long pc
, unsigned long *startp
,
1193 unsigned long *endp
)
1195 unsigned long size
, offset
;
1199 *startp
= *endp
= 0;
1202 if (setjmp(bus_error_jmp
) == 0) {
1203 catch_memory_errors
= 1;
1205 name
= kallsyms_lookup(pc
, &size
, &offset
, &modname
, tmpstr
);
1207 *startp
= pc
- offset
;
1208 *endp
= pc
- offset
+ size
;
1212 catch_memory_errors
= 0;
1215 static int xmon_depth_to_print
= 64;
1218 #define LRSAVE_OFFSET 0x10
1219 #define REG_FRAME_MARKER 0x7265677368657265ul /* "regshere" */
1220 #define MARKER_OFFSET 0x60
1221 #define REGS_OFFSET 0x70
1223 #define LRSAVE_OFFSET 4
1224 #define REG_FRAME_MARKER 0x72656773
1225 #define MARKER_OFFSET 8
1226 #define REGS_OFFSET 16
1229 static void xmon_show_stack(unsigned long sp
, unsigned long lr
,
1233 unsigned long newsp
;
1234 unsigned long marker
;
1236 struct pt_regs regs
;
1239 if (sp
< PAGE_OFFSET
) {
1241 printf("SP (%lx) is in userspace\n", sp
);
1245 if (!mread(sp
+ LRSAVE_OFFSET
, &ip
, sizeof(unsigned long))
1246 || !mread(sp
, &newsp
, sizeof(unsigned long))) {
1247 printf("Couldn't read stack frame at %lx\n", sp
);
1252 * For the first stack frame, try to work out if
1253 * LR and/or the saved LR value in the bottommost
1254 * stack frame are valid.
1256 if ((pc
| lr
) != 0) {
1257 unsigned long fnstart
, fnend
;
1258 unsigned long nextip
;
1261 get_function_bounds(pc
, &fnstart
, &fnend
);
1264 mread(newsp
+ LRSAVE_OFFSET
, &nextip
,
1265 sizeof(unsigned long));
1267 if (lr
< PAGE_OFFSET
1268 || (fnstart
<= lr
&& lr
< fnend
))
1270 } else if (lr
== nextip
) {
1272 } else if (lr
>= PAGE_OFFSET
1273 && !(fnstart
<= lr
&& lr
< fnend
)) {
1274 printf("[link register ] ");
1275 xmon_print_symbol(lr
, " ", "\n");
1278 printf("["REG
"] ", sp
);
1279 xmon_print_symbol(ip
, " ", " (unreliable)\n");
1284 printf("["REG
"] ", sp
);
1285 xmon_print_symbol(ip
, " ", "\n");
1288 /* Look for "regshere" marker to see if this is
1289 an exception frame. */
1290 if (mread(sp
+ MARKER_OFFSET
, &marker
, sizeof(unsigned long))
1291 && marker
== REG_FRAME_MARKER
) {
1292 if (mread(sp
+ REGS_OFFSET
, ®s
, sizeof(regs
))
1294 printf("Couldn't read registers at %lx\n",
1298 printf("--- Exception: %lx %s at ", regs
.trap
,
1299 getvecname(TRAP(®s
)));
1302 xmon_print_symbol(pc
, " ", "\n");
1309 } while (count
++ < xmon_depth_to_print
);
1312 static void backtrace(struct pt_regs
*excp
)
1317 xmon_show_stack(sp
, 0, 0);
1319 xmon_show_stack(excp
->gpr
[1], excp
->link
, excp
->nip
);
1323 static void print_bug_trap(struct pt_regs
*regs
)
1325 struct bug_entry
*bug
;
1328 if (regs
->msr
& MSR_PR
)
1329 return; /* not in kernel */
1330 addr
= regs
->nip
; /* address of trap instruction */
1331 if (addr
< PAGE_OFFSET
)
1333 bug
= find_bug(regs
->nip
);
1336 if (bug
->line
& BUG_WARNING_TRAP
)
1339 printf("kernel BUG in %s at %s:%d!\n",
1340 bug
->function
, bug
->file
, (unsigned int)bug
->line
);
1343 void excprint(struct pt_regs
*fp
)
1348 printf("cpu 0x%x: ", smp_processor_id());
1349 #endif /* CONFIG_SMP */
1352 printf("Vector: %lx %s at [%lx]\n", fp
->trap
, getvecname(trap
), fp
);
1354 xmon_print_symbol(fp
->nip
, ": ", "\n");
1356 printf(" lr: ", fp
->link
);
1357 xmon_print_symbol(fp
->link
, ": ", "\n");
1359 printf(" sp: %lx\n", fp
->gpr
[1]);
1360 printf(" msr: %lx\n", fp
->msr
);
1362 if (trap
== 0x300 || trap
== 0x380 || trap
== 0x600) {
1363 printf(" dar: %lx\n", fp
->dar
);
1365 printf(" dsisr: %lx\n", fp
->dsisr
);
1368 printf(" current = 0x%lx\n", current
);
1370 printf(" paca = 0x%lx\n", get_paca());
1373 printf(" pid = %ld, comm = %s\n",
1374 current
->pid
, current
->comm
);
1381 void prregs(struct pt_regs
*fp
)
1385 struct pt_regs regs
;
1387 if (scanhex(&base
)) {
1388 if (setjmp(bus_error_jmp
) == 0) {
1389 catch_memory_errors
= 1;
1391 regs
= *(struct pt_regs
*)base
;
1395 catch_memory_errors
= 0;
1396 printf("*** Error reading registers from "REG
"\n",
1400 catch_memory_errors
= 0;
1405 if (FULL_REGS(fp
)) {
1406 for (n
= 0; n
< 16; ++n
)
1407 printf("R%.2ld = "REG
" R%.2ld = "REG
"\n",
1408 n
, fp
->gpr
[n
], n
+16, fp
->gpr
[n
+16]);
1410 for (n
= 0; n
< 7; ++n
)
1411 printf("R%.2ld = "REG
" R%.2ld = "REG
"\n",
1412 n
, fp
->gpr
[n
], n
+7, fp
->gpr
[n
+7]);
1415 for (n
= 0; n
< 32; ++n
) {
1416 printf("R%.2d = %.8x%s", n
, fp
->gpr
[n
],
1417 (n
& 3) == 3? "\n": " ");
1418 if (n
== 12 && !FULL_REGS(fp
)) {
1425 xmon_print_symbol(fp
->nip
, " ", "\n");
1427 xmon_print_symbol(fp
->link
, " ", "\n");
1428 printf("msr = "REG
" cr = %.8lx\n", fp
->msr
, fp
->ccr
);
1429 printf("ctr = "REG
" xer = "REG
" trap = %4lx\n",
1430 fp
->ctr
, fp
->xer
, fp
->trap
);
1432 if (trap
== 0x300 || trap
== 0x380 || trap
== 0x600)
1433 printf("dar = "REG
" dsisr = %.8lx\n", fp
->dar
, fp
->dsisr
);
1436 void cacheflush(void)
1439 unsigned long nflush
;
1444 scanhex((void *)&adrs
);
1449 nflush
= (nflush
+ L1_CACHE_BYTES
- 1) / L1_CACHE_BYTES
;
1450 if (setjmp(bus_error_jmp
) == 0) {
1451 catch_memory_errors
= 1;
1455 for (; nflush
> 0; --nflush
, adrs
+= L1_CACHE_BYTES
)
1456 cflush((void *) adrs
);
1458 for (; nflush
> 0; --nflush
, adrs
+= L1_CACHE_BYTES
)
1459 cinval((void *) adrs
);
1462 /* wait a little while to see if we get a machine check */
1465 catch_memory_errors
= 0;
1471 unsigned int instrs
[2];
1472 unsigned long (*code
)(void);
1473 unsigned long ret
= -1UL;
1475 unsigned long opd
[3];
1477 opd
[0] = (unsigned long)instrs
;
1480 code
= (unsigned long (*)(void)) opd
;
1482 code
= (unsigned long (*)(void)) instrs
;
1485 /* mfspr r3,n; blr */
1486 instrs
[0] = 0x7c6002a6 + ((n
& 0x1F) << 16) + ((n
& 0x3e0) << 6);
1487 instrs
[1] = 0x4e800020;
1489 store_inst(instrs
+1);
1491 if (setjmp(bus_error_jmp
) == 0) {
1492 catch_memory_errors
= 1;
1498 /* wait a little while to see if we get a machine check */
1507 write_spr(int n
, unsigned long val
)
1509 unsigned int instrs
[2];
1510 unsigned long (*code
)(unsigned long);
1512 unsigned long opd
[3];
1514 opd
[0] = (unsigned long)instrs
;
1517 code
= (unsigned long (*)(unsigned long)) opd
;
1519 code
= (unsigned long (*)(unsigned long)) instrs
;
1522 instrs
[0] = 0x7c6003a6 + ((n
& 0x1F) << 16) + ((n
& 0x3e0) << 6);
1523 instrs
[1] = 0x4e800020;
1525 store_inst(instrs
+1);
1527 if (setjmp(bus_error_jmp
) == 0) {
1528 catch_memory_errors
= 1;
1534 /* wait a little while to see if we get a machine check */
1540 static unsigned long regno
;
1541 extern char exc_prolog
;
1542 extern char dec_exc
;
1544 void super_regs(void)
1548 #ifdef CONFIG_PPC_ISERIES
1549 struct paca_struct
*ptrPaca
= NULL
;
1550 struct lppaca
*ptrLpPaca
= NULL
;
1551 struct ItLpRegSave
*ptrLpRegSave
= NULL
;
1556 unsigned long sp
, toc
;
1557 asm("mr %0,1" : "=r" (sp
) :);
1558 asm("mr %0,2" : "=r" (toc
) :);
1560 printf("msr = "REG
" sprg0= "REG
"\n",
1561 mfmsr(), mfspr(SPRN_SPRG0
));
1562 printf("pvr = "REG
" sprg1= "REG
"\n",
1563 mfspr(SPRN_PVR
), mfspr(SPRN_SPRG1
));
1564 printf("dec = "REG
" sprg2= "REG
"\n",
1565 mfspr(SPRN_DEC
), mfspr(SPRN_SPRG2
));
1566 printf("sp = "REG
" sprg3= "REG
"\n", sp
, mfspr(SPRN_SPRG3
));
1567 printf("toc = "REG
" dar = "REG
"\n", toc
, mfspr(SPRN_DAR
));
1568 #ifdef CONFIG_PPC_ISERIES
1569 // Dump out relevant Paca data areas.
1571 ptrPaca
= get_paca();
1573 printf(" Local Processor Control Area (LpPaca): \n");
1574 ptrLpPaca
= ptrPaca
->lppaca_ptr
;
1575 printf(" Saved Srr0=%.16lx Saved Srr1=%.16lx \n",
1576 ptrLpPaca
->saved_srr0
, ptrLpPaca
->saved_srr1
);
1577 printf(" Saved Gpr3=%.16lx Saved Gpr4=%.16lx \n",
1578 ptrLpPaca
->saved_gpr3
, ptrLpPaca
->saved_gpr4
);
1579 printf(" Saved Gpr5=%.16lx \n", ptrLpPaca
->saved_gpr5
);
1581 printf(" Local Processor Register Save Area (LpRegSave): \n");
1582 ptrLpRegSave
= ptrPaca
->reg_save_ptr
;
1583 printf(" Saved Sprg0=%.16lx Saved Sprg1=%.16lx \n",
1584 ptrLpRegSave
->xSPRG0
, ptrLpRegSave
->xSPRG0
);
1585 printf(" Saved Sprg2=%.16lx Saved Sprg3=%.16lx \n",
1586 ptrLpRegSave
->xSPRG2
, ptrLpRegSave
->xSPRG3
);
1587 printf(" Saved Msr =%.16lx Saved Nia =%.16lx \n",
1588 ptrLpRegSave
->xMSR
, ptrLpRegSave
->xNIA
);
1597 val
= read_spr(regno
);
1599 write_spr(regno
, val
);
1602 printf("spr %lx = %lx\n", regno
, read_spr(regno
));
1609 * Stuff for reading and writing memory safely
1612 mread(unsigned long adrs
, void *buf
, int size
)
1618 if (setjmp(bus_error_jmp
) == 0) {
1619 catch_memory_errors
= 1;
1625 *(u16
*)q
= *(u16
*)p
;
1628 *(u32
*)q
= *(u32
*)p
;
1631 *(u64
*)q
= *(u64
*)p
;
1634 for( ; n
< size
; ++n
) {
1640 /* wait a little while to see if we get a machine check */
1644 catch_memory_errors
= 0;
1649 mwrite(unsigned long adrs
, void *buf
, int size
)
1655 if (setjmp(bus_error_jmp
) == 0) {
1656 catch_memory_errors
= 1;
1662 *(u16
*)p
= *(u16
*)q
;
1665 *(u32
*)p
= *(u32
*)q
;
1668 *(u64
*)p
= *(u64
*)q
;
1671 for ( ; n
< size
; ++n
) {
1677 /* wait a little while to see if we get a machine check */
1681 printf("*** Error writing address %x\n", adrs
+ n
);
1683 catch_memory_errors
= 0;
1687 static int fault_type
;
1688 static int fault_except
;
1689 static char *fault_chars
[] = { "--", "**", "##" };
1691 static int handle_fault(struct pt_regs
*regs
)
1693 fault_except
= TRAP(regs
);
1694 switch (TRAP(regs
)) {
1706 longjmp(bus_error_jmp
, 1);
1711 #define SWAP(a, b, t) ((t) = (a), (a) = (b), (b) = (t))
1714 byterev(unsigned char *val
, int size
)
1720 SWAP(val
[0], val
[1], t
);
1723 SWAP(val
[0], val
[3], t
);
1724 SWAP(val
[1], val
[2], t
);
1726 case 8: /* is there really any use for this? */
1727 SWAP(val
[0], val
[7], t
);
1728 SWAP(val
[1], val
[6], t
);
1729 SWAP(val
[2], val
[5], t
);
1730 SWAP(val
[3], val
[4], t
);
1738 static char *memex_help_string
=
1739 "Memory examine command usage:\n"
1740 "m [addr] [flags] examine/change memory\n"
1741 " addr is optional. will start where left off.\n"
1742 " flags may include chars from this set:\n"
1743 " b modify by bytes (default)\n"
1744 " w modify by words (2 byte)\n"
1745 " l modify by longs (4 byte)\n"
1746 " d modify by doubleword (8 byte)\n"
1747 " r toggle reverse byte order mode\n"
1748 " n do not read memory (for i/o spaces)\n"
1749 " . ok to read (default)\n"
1750 "NOTE: flags are saved as defaults\n"
1753 static char *memex_subcmd_help_string
=
1754 "Memory examine subcommands:\n"
1755 " hexval write this val to current location\n"
1756 " 'string' write chars from string to this location\n"
1757 " ' increment address\n"
1758 " ^ decrement address\n"
1759 " / increment addr by 0x10. //=0x100, ///=0x1000, etc\n"
1760 " \\ decrement addr by 0x10. \\\\=0x100, \\\\\\=0x1000, etc\n"
1761 " ` clear no-read flag\n"
1762 " ; stay at this addr\n"
1763 " v change to byte mode\n"
1764 " w change to word (2 byte) mode\n"
1765 " l change to long (4 byte) mode\n"
1766 " u change to doubleword (8 byte) mode\n"
1767 " m addr change current addr\n"
1768 " n toggle no-read flag\n"
1769 " r toggle byte reverse flag\n"
1770 " < count back up count bytes\n"
1771 " > count skip forward count bytes\n"
1772 " x exit this mode\n"
1778 int cmd
, inc
, i
, nslash
;
1780 unsigned char val
[16];
1782 scanhex((void *)&adrs
);
1785 printf(memex_help_string
);
1791 while ((cmd
= skipbl()) != '\n') {
1793 case 'b': size
= 1; break;
1794 case 'w': size
= 2; break;
1795 case 'l': size
= 4; break;
1796 case 'd': size
= 8; break;
1797 case 'r': brev
= !brev
; break;
1798 case 'n': mnoread
= 1; break;
1799 case '.': mnoread
= 0; break;
1808 n
= mread(adrs
, val
, size
);
1809 printf(REG
"%c", adrs
, brev
? 'r': ' ');
1814 for (i
= 0; i
< n
; ++i
)
1815 printf("%.2x", val
[i
]);
1816 for (; i
< size
; ++i
)
1817 printf("%s", fault_chars
[fault_type
]);
1824 for (i
= 0; i
< size
; ++i
)
1825 val
[i
] = n
>> (i
* 8);
1828 mwrite(adrs
, val
, size
);
1841 else if( n
== '\'' )
1843 for (i
= 0; i
< size
; ++i
)
1844 val
[i
] = n
>> (i
* 8);
1847 mwrite(adrs
, val
, size
);
1884 adrs
-= 1 << nslash
;
1888 adrs
+= 1 << nslash
;
1892 adrs
+= 1 << -nslash
;
1896 adrs
-= 1 << -nslash
;
1899 scanhex((void *)&adrs
);
1918 printf(memex_subcmd_help_string
);
1933 case 'n': c
= '\n'; break;
1934 case 'r': c
= '\r'; break;
1935 case 'b': c
= '\b'; break;
1936 case 't': c
= '\t'; break;
1941 #define isxdigit(c) (('0' <= (c) && (c) <= '9') \
1942 || ('a' <= (c) && (c) <= 'f') \
1943 || ('A' <= (c) && (c) <= 'F'))
1950 if ((isxdigit(c
) && c
!= 'f' && c
!= 'd') || c
== '\n')
1952 scanhex((void *)&adrs
);
1959 else if (nidump
> MAX_DUMP
)
1961 adrs
+= ppc_inst_dump(adrs
, nidump
, 1);
1967 else if (ndump
> MAX_DUMP
)
1969 prdump(adrs
, ndump
);
1976 prdump(unsigned long adrs
, long ndump
)
1978 long n
, m
, c
, r
, nr
;
1979 unsigned char temp
[16];
1981 for (n
= ndump
; n
> 0;) {
1985 nr
= mread(adrs
, temp
, r
);
1987 for (m
= 0; m
< r
; ++m
) {
1988 if ((m
& (sizeof(long) - 1)) == 0 && m
> 0)
1991 printf("%.2x", temp
[m
]);
1993 printf("%s", fault_chars
[fault_type
]);
1995 for (; m
< 16; ++m
) {
1996 if ((m
& (sizeof(long) - 1)) == 0)
2001 for (m
= 0; m
< r
; ++m
) {
2004 putchar(' ' <= c
&& c
<= '~'? c
: '.');
2018 ppc_inst_dump(unsigned long adr
, long count
, int praddr
)
2021 unsigned long first_adr
;
2022 unsigned long inst
, last_inst
= 0;
2023 unsigned char val
[4];
2026 for (first_adr
= adr
; count
> 0; --count
, adr
+= 4) {
2027 nr
= mread(adr
, val
, 4);
2030 const char *x
= fault_chars
[fault_type
];
2031 printf(REG
" %s%s%s%s\n", adr
, x
, x
, x
, x
);
2035 inst
= GETWORD(val
);
2036 if (adr
> first_adr
&& inst
== last_inst
) {
2046 printf(REG
" %.8x", adr
, inst
);
2048 print_insn_powerpc(inst
, adr
, 0); /* always returns 4 */
2051 return adr
- first_adr
;
2055 print_address(unsigned long addr
)
2057 xmon_print_symbol(addr
, "\t# ", "");
2062 * Memory operations - move, set, print differences
2064 static unsigned long mdest
; /* destination address */
2065 static unsigned long msrc
; /* source address */
2066 static unsigned long mval
; /* byte value to set memory to */
2067 static unsigned long mcount
; /* # bytes to affect */
2068 static unsigned long mdiffs
; /* max # differences to print */
2073 scanhex((void *)&mdest
);
2074 if( termch
!= '\n' )
2076 scanhex((void *)(cmd
== 's'? &mval
: &msrc
));
2077 if( termch
!= '\n' )
2079 scanhex((void *)&mcount
);
2082 memmove((void *)mdest
, (void *)msrc
, mcount
);
2085 memset((void *)mdest
, mval
, mcount
);
2088 if( termch
!= '\n' )
2090 scanhex((void *)&mdiffs
);
2091 memdiffs((unsigned char *)mdest
, (unsigned char *)msrc
, mcount
, mdiffs
);
2097 memdiffs(unsigned char *p1
, unsigned char *p2
, unsigned nb
, unsigned maxpr
)
2102 for( n
= nb
; n
> 0; --n
)
2103 if( *p1
++ != *p2
++ )
2104 if( ++prt
<= maxpr
)
2105 printf("%.16x %.2x # %.16x %.2x\n", p1
- 1,
2106 p1
[-1], p2
- 1, p2
[-1]);
2108 printf("Total of %d differences\n", prt
);
2111 static unsigned mend
;
2112 static unsigned mask
;
2118 unsigned char val
[4];
2121 scanhex((void *)&mdest
);
2122 if (termch
!= '\n') {
2124 scanhex((void *)&mend
);
2125 if (termch
!= '\n') {
2127 scanhex((void *)&mval
);
2129 if (termch
!= '\n') termch
= 0;
2130 scanhex((void *)&mask
);
2134 for (a
= mdest
; a
< mend
; a
+= 4) {
2135 if (mread(a
, val
, 4) == 4
2136 && ((GETWORD(val
) ^ mval
) & mask
) == 0) {
2137 printf("%.16x: %.16x\n", a
, GETWORD(val
));
2144 static unsigned long mskip
= 0x1000;
2145 static unsigned long mlim
= 0xffffffff;
2155 if (termch
!= '\n') termch
= 0;
2157 if (termch
!= '\n') termch
= 0;
2160 for (a
= mdest
; a
< mlim
; a
+= mskip
) {
2161 ok
= mread(a
, &v
, 1);
2163 printf("%.8x .. ", a
);
2164 } else if (!ok
&& ook
)
2165 printf("%.8x\n", a
- mskip
);
2171 printf("%.8x\n", a
- mskip
);
2176 unsigned long args
[8];
2179 typedef unsigned long (*callfunc_t
)(unsigned long, unsigned long,
2180 unsigned long, unsigned long, unsigned long,
2181 unsigned long, unsigned long, unsigned long);
2184 if (!scanhex(&adrs
))
2188 for (i
= 0; i
< 8; ++i
)
2190 for (i
= 0; i
< 8; ++i
) {
2191 if (!scanhex(&args
[i
]) || termch
== '\n')
2195 func
= (callfunc_t
) adrs
;
2197 if (setjmp(bus_error_jmp
) == 0) {
2198 catch_memory_errors
= 1;
2200 ret
= func(args
[0], args
[1], args
[2], args
[3],
2201 args
[4], args
[5], args
[6], args
[7]);
2203 printf("return value is %x\n", ret
);
2205 printf("*** %x exception occurred\n", fault_except
);
2207 catch_memory_errors
= 0;
2210 /* Input scanning routines */
2221 while( c
== ' ' || c
== '\t' )
2227 static char *regnames
[N_PTREGS
] = {
2228 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
2229 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
2230 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
2231 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
2232 "pc", "msr", "or3", "ctr", "lr", "xer", "ccr",
2238 "trap", "dar", "dsisr", "res"
2242 scanhex(unsigned long *vp
)
2249 /* parse register name */
2253 for (i
= 0; i
< sizeof(regname
) - 1; ++i
) {
2262 for (i
= 0; i
< N_PTREGS
; ++i
) {
2263 if (strcmp(regnames
[i
], regname
) == 0) {
2264 if (xmon_regs
== NULL
) {
2265 printf("regs not available\n");
2268 *vp
= ((unsigned long *)xmon_regs
)[i
];
2272 printf("invalid register name '%%%s'\n", regname
);
2276 /* skip leading "0x" if any */
2290 } else if (c
== '$') {
2292 for (i
=0; i
<63; i
++) {
2302 if (setjmp(bus_error_jmp
) == 0) {
2303 catch_memory_errors
= 1;
2305 *vp
= kallsyms_lookup_name(tmpstr
);
2308 catch_memory_errors
= 0;
2310 printf("unknown symbol '%s'\n", tmpstr
);
2345 if( '0' <= c
&& c
<= '9' )
2347 if( 'A' <= c
&& c
<= 'F' )
2348 return c
- ('A' - 10);
2349 if( 'a' <= c
&& c
<= 'f' )
2350 return c
- ('a' - 10);
2355 getstring(char *s
, int size
)
2366 } while( c
!= ' ' && c
!= '\t' && c
!= '\n' );
2371 static char line
[256];
2372 static char *lineptr
;
2383 if (lineptr
== NULL
|| *lineptr
== 0) {
2384 if (xmon_gets(line
, sizeof(line
)) == NULL
) {
2394 take_input(char *str
)
2403 int type
= inchar();
2405 static char tmp
[64];
2410 xmon_print_symbol(addr
, ": ", "\n");
2415 if (setjmp(bus_error_jmp
) == 0) {
2416 catch_memory_errors
= 1;
2418 addr
= kallsyms_lookup_name(tmp
);
2420 printf("%s: %lx\n", tmp
, addr
);
2422 printf("Symbol '%s' not found.\n", tmp
);
2425 catch_memory_errors
= 0;
2432 /* Print an address in numeric and symbolic form (if possible) */
2433 static void xmon_print_symbol(unsigned long address
, const char *mid
,
2437 const char *name
= NULL
;
2438 unsigned long offset
, size
;
2440 printf(REG
, address
);
2441 if (setjmp(bus_error_jmp
) == 0) {
2442 catch_memory_errors
= 1;
2444 name
= kallsyms_lookup(address
, &size
, &offset
, &modname
,
2447 /* wait a little while to see if we get a machine check */
2451 catch_memory_errors
= 0;
2454 printf("%s%s+%#lx/%#lx", mid
, name
, offset
, size
);
2456 printf(" [%s]", modname
);
2458 printf("%s", after
);
2462 static void dump_slb(void)
2467 printf("SLB contents of cpu %x\n", smp_processor_id());
2469 for (i
= 0; i
< SLB_NUM_ENTRIES
; i
++) {
2470 asm volatile("slbmfee %0,%1" : "=r" (tmp
) : "r" (i
));
2471 printf("%02d %016lx ", i
, tmp
);
2473 asm volatile("slbmfev %0,%1" : "=r" (tmp
) : "r" (i
));
2474 printf("%016lx\n", tmp
);
2478 static void dump_stab(void)
2481 unsigned long *tmp
= (unsigned long *)get_paca()->stab_addr
;
2483 printf("Segment table contents of cpu %x\n", smp_processor_id());
2485 for (i
= 0; i
< PAGE_SIZE
/16; i
++) {
2492 printf("%03d %016lx ", i
, a
);
2493 printf("%016lx\n", b
);
2498 void dump_segments(void)
2500 if (cpu_has_feature(CPU_FTR_SLB
))
2507 #ifdef CONFIG_PPC_STD_MMU_32
2508 void dump_segments(void)
2513 for (i
= 0; i
< 16; ++i
)
2514 printf(" %x", mfsrin(i
));
2519 void xmon_init(int enable
)
2523 __debugger_ipi
= xmon_ipi
;
2524 __debugger_bpt
= xmon_bpt
;
2525 __debugger_sstep
= xmon_sstep
;
2526 __debugger_iabr_match
= xmon_iabr_match
;
2527 __debugger_dabr_match
= xmon_dabr_match
;
2528 __debugger_fault_handler
= xmon_fault_handler
;
2531 __debugger_ipi
= NULL
;
2532 __debugger_bpt
= NULL
;
2533 __debugger_sstep
= NULL
;
2534 __debugger_iabr_match
= NULL
;
2535 __debugger_dabr_match
= NULL
;
2536 __debugger_fault_handler
= NULL
;
2541 #ifdef CONFIG_MAGIC_SYSRQ
2542 static void sysrq_handle_xmon(int key
, struct pt_regs
*pt_regs
,
2543 struct tty_struct
*tty
)
2545 /* ensure xmon is enabled */
2550 static struct sysrq_key_op sysrq_xmon_op
=
2552 .handler
= sysrq_handle_xmon
,
2554 .action_msg
= "Entering xmon",
2557 static int __init
setup_xmon_sysrq(void)
2559 register_sysrq_key('x', &sysrq_xmon_op
);
2562 __initcall(setup_xmon_sysrq
);
2563 #endif /* CONFIG_MAGIC_SYSRQ */