2 * Routines providing a simple monitor for use on the PowerMac.
4 * Copyright (C) 1996 Paul Mackerras.
6 #include <linux/config.h>
7 #include <linux/errno.h>
8 #include <linux/sched.h>
10 #include <linux/interrupt.h>
11 #include <linux/bitops.h>
12 #include <linux/kallsyms.h>
13 #include <asm/ptrace.h>
14 #include <asm/string.h>
16 #include <asm/bootx.h>
17 #include <asm/machdep.h>
19 #ifdef CONFIG_PMAC_BACKLIGHT
20 #include <asm/backlight.h>
25 #define scanhex xmon_scanhex
26 #define skipbl xmon_skipbl
29 static unsigned long cpus_in_xmon
= 0;
30 static unsigned long got_xmon
= 0;
31 static volatile int take_xmon
= -1;
32 #endif /* CONFIG_SMP */
36 static unsigned ndump
= 64;
37 static unsigned nidump
= 16;
38 static unsigned ncsum
= 4096;
41 static u_int bus_error_jmp
[100];
42 #define setjmp xmon_setjmp
43 #define longjmp xmon_longjmp
45 /* Breakpoint stuff */
50 unsigned char enabled
;
54 static struct bpt bpts
[NBPTS
];
55 static struct bpt dabr
;
56 static struct bpt iabr
;
57 static unsigned bpinstr
= 0x7fe00008; /* trap */
60 extern void (*debugger_fault_handler
)(struct pt_regs
*);
61 static int cmds(struct pt_regs
*);
62 static int mread(unsigned, void *, int);
63 static int mwrite(unsigned, void *, int);
64 static void handle_fault(struct pt_regs
*);
65 static void byterev(unsigned char *, int);
66 static void memex(void);
67 static int bsesc(void);
68 static void dump(void);
69 static void prdump(unsigned, int);
71 static void prndump(unsigned, int);
72 static int nvreadb(unsigned);
74 static int ppc_inst_dump(unsigned, int);
75 void print_address(unsigned);
76 static int getsp(void);
77 static void dump_hash_table(void);
78 static void backtrace(struct pt_regs
*);
79 static void excprint(struct pt_regs
*);
80 static void prregs(struct pt_regs
*);
81 static void memops(int);
82 static void memlocate(void);
83 static void memzcan(void);
84 static void memdiffs(unsigned char *, unsigned char *, unsigned, unsigned);
86 int scanhex(unsigned *valp
);
87 static void scannl(void);
88 static int hexdigit(int);
89 void getstring(char *, int);
90 static void flush_input(void);
91 static int inchar(void);
92 static void take_input(char *);
93 /* static void openforth(void); */
94 static unsigned read_spr(int);
95 static void write_spr(int, unsigned);
96 static void super_regs(void);
97 static void symbol_lookup(void);
98 static void remove_bpts(void);
99 static void insert_bpts(void);
100 static struct bpt
*at_breakpoint(unsigned pc
);
101 static void bpt_cmds(void);
102 static void cacheflush(void);
104 static void cpu_cmd(void);
105 #endif /* CONFIG_SMP */
106 static void csum(void);
107 #ifdef CONFIG_BOOTX_TEXT
108 static void vidcmds(void);
110 static void bootcmds(void);
111 static void proccall(void);
112 static void printtime(void);
114 extern int print_insn_big_powerpc(FILE *, unsigned long, unsigned);
115 extern void printf(const char *fmt
, ...);
116 extern int putchar(int ch
);
117 extern int setjmp(u_int
*);
118 extern void longjmp(u_int
*, int);
120 extern void xmon_enter(void);
121 extern void xmon_leave(void);
123 static unsigned start_tb
[NR_CPUS
][2];
124 static unsigned stop_tb
[NR_CPUS
][2];
126 #define GETWORD(v) (((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
128 #define isxdigit(c) (('0' <= (c) && (c) <= '9') \
129 || ('a' <= (c) && (c) <= 'f') \
130 || ('A' <= (c) && (c) <= 'F'))
131 #define isalnum(c) (('0' <= (c) && (c) <= '9') \
132 || ('a' <= (c) && (c) <= 'z') \
133 || ('A' <= (c) && (c) <= 'Z'))
134 #define isspace(c) (c == ' ' || c == '\t' || c == 10 || c == 13 || c == 0)
136 static char *help_string
= "\
139 di dump instructions\n\
140 df dump float values\n\
141 dd dump double values\n\
142 e print exception information\n\
144 m examine/change memory\n\
145 mm move a block of memory\n\
146 ms set a block of memory\n\
147 md compare two blocks of memory\n\
149 S print special registers\n\
151 la lookup address in system.map\n\
152 ls lookup symbol in system.map\n\
156 static int xmon_trace
[NR_CPUS
];
157 #define SSTEP 1 /* stepping because of 's' command */
158 #define BRSTEP 2 /* stepping over breakpoint */
160 static struct pt_regs
*xmon_regs
[NR_CPUS
];
162 extern inline void sync(void)
164 asm volatile("sync; isync");
167 extern inline void __delay(unsigned int loops
)
170 __asm__
__volatile__("mtctr %0; 1: bdnz 1b" : :
171 "r" (loops
) : "ctr");
174 /* Print an address in numeric and symbolic form (if possible) */
175 static void xmon_print_symbol(unsigned long address
, const char *mid
,
179 const char *name
= NULL
;
180 unsigned long offset
, size
;
181 static char tmpstr
[128];
183 printf("%.8lx", address
);
184 if (setjmp(bus_error_jmp
) == 0) {
185 debugger_fault_handler
= handle_fault
;
187 name
= kallsyms_lookup(address
, &size
, &offset
, &modname
,
190 /* wait a little while to see if we get a machine check */
193 debugger_fault_handler
= NULL
;
196 printf("%s%s+%#lx/%#lx", mid
, name
, offset
, size
);
198 printf(" [%s]", modname
);
203 static void get_tb(unsigned *p
)
205 unsigned hi
, lo
, hiagain
;
207 if ((get_pvr() >> 16) == 1)
211 asm volatile("mftbu %0; mftb %1; mftbu %2"
212 : "=r" (hi
), "=r" (lo
), "=r" (hiagain
));
213 } while (hi
!= hiagain
);
219 xmon(struct pt_regs
*excp
)
224 get_tb(stop_tb
[smp_processor_id()]);
226 asm volatile ("stw 0,0(%0)\n\
229 stmw 2,8(%0)" : : "b" (®s
));
230 regs
.nip
= regs
.link
= ((unsigned long *)regs
.gpr
[1])[1];
231 regs
.msr
= get_msr();
232 regs
.ctr
= get_ctr();
233 regs
.xer
= get_xer();
240 set_msr(msr
& ~0x8000); /* disable interrupts */
241 xmon_regs
[smp_processor_id()] = excp
;
245 if (test_and_set_bit(smp_processor_id(), &cpus_in_xmon
))
248 while (test_and_set_bit(0, &got_xmon
)) {
249 if (take_xmon
== smp_processor_id()) {
255 * XXX: breakpoints are removed while any cpu is in xmon
257 #endif /* CONFIG_SMP */
259 #ifdef CONFIG_PMAC_BACKLIGHT
260 if( setjmp(bus_error_jmp
) == 0 ) {
261 debugger_fault_handler
= handle_fault
;
263 set_backlight_enable(1);
264 set_backlight_level(BACKLIGHT_MAX
);
267 debugger_fault_handler
= NULL
;
268 #endif /* CONFIG_PMAC_BACKLIGHT */
271 xmon_trace
[smp_processor_id()] = SSTEP
;
273 } else if (at_breakpoint(excp
->nip
)) {
274 xmon_trace
[smp_processor_id()] = BRSTEP
;
277 xmon_trace
[smp_processor_id()] = 0;
281 xmon_regs
[smp_processor_id()] = NULL
;
283 clear_bit(0, &got_xmon
);
284 clear_bit(smp_processor_id(), &cpus_in_xmon
);
285 #endif /* CONFIG_SMP */
286 set_msr(msr
); /* restore interrupt enable */
287 get_tb(start_tb
[smp_processor_id()]);
291 xmon_irq(int irq
, void *d
, struct pt_regs
*regs
)
294 local_irq_save(flags
);
295 printf("Keyboard interrupt\n");
297 local_irq_restore(flags
);
302 xmon_bpt(struct pt_regs
*regs
)
306 bp
= at_breakpoint(regs
->nip
);
313 xmon_trace
[smp_processor_id()] = BRSTEP
;
322 xmon_sstep(struct pt_regs
*regs
)
324 if (!xmon_trace
[smp_processor_id()])
326 if (xmon_trace
[smp_processor_id()] == BRSTEP
) {
327 xmon_trace
[smp_processor_id()] = 0;
336 xmon_dabr_match(struct pt_regs
*regs
)
338 if (dabr
.enabled
&& dabr
.count
) {
342 xmon_trace
[smp_processor_id()] = BRSTEP
;
345 dabr
.instr
= regs
->nip
;
352 xmon_iabr_match(struct pt_regs
*regs
)
354 if (iabr
.enabled
&& iabr
.count
) {
358 xmon_trace
[smp_processor_id()] = BRSTEP
;
367 at_breakpoint(unsigned pc
)
372 if (dabr
.enabled
&& pc
== dabr
.instr
)
374 if (iabr
.enabled
&& pc
== iabr
.address
)
377 for (i
= 0; i
< NBPTS
; ++i
, ++bp
)
378 if (bp
->enabled
&& pc
== bp
->address
)
390 for (i
= 0; i
< NBPTS
; ++i
, ++bp
) {
393 if (mread(bp
->address
, &bp
->instr
, 4) != 4
394 || mwrite(bp
->address
, &bpinstr
, 4) != 4) {
395 printf("Couldn't insert breakpoint at %x, disabling\n",
399 store_inst((void *) bp
->address
);
401 #if !defined(CONFIG_8xx)
403 set_dabr(dabr
.address
);
405 set_iabr(iabr
.address
);
416 #if !defined(CONFIG_8xx)
421 for (i
= 0; i
< NBPTS
; ++i
, ++bp
) {
424 if (mread(bp
->address
, &instr
, 4) == 4
426 && mwrite(bp
->address
, &bp
->instr
, 4) != 4)
427 printf("Couldn't remove breakpoint at %x\n",
429 store_inst((void *) bp
->address
);
433 static char *last_cmd
;
435 /* Command interpreting routine */
437 cmds(struct pt_regs
*excp
)
444 printf("%d:", smp_processor_id());
445 #endif /* CONFIG_SMP */
452 if (last_cmd
== NULL
)
454 take_input(last_cmd
);
486 prregs(excp
); /* print regs */
490 printf("No exception information\n");
514 printf("Unrecognized command: ");
515 if( ' ' < cmd
&& cmd
<= '~' )
518 printf("\\x%x", cmd
);
519 printf(" (type ? for help)\n");
531 #endif /* CONFIG_SMP */
532 #ifdef CONFIG_BOOTX_TEXT
550 extern unsigned tb_to_us
;
552 #define mulhwu(x,y) \
553 ({unsigned z; asm ("mulhwu %0,%1,%2" : "=r" (z) : "r" (x), "r" (y)); z;})
555 static void printtime(void)
559 delta
= stop_tb
[smp_processor_id()][1]
560 - start_tb
[smp_processor_id()][1];
561 delta
= mulhwu(tb_to_us
, delta
);
562 printf("%u.%06u seconds\n", delta
/ 1000000, delta
% 1000000);
565 static void bootcmds(void)
571 ppc_md
.restart(NULL
);
579 static void cpu_cmd(void)
587 /* interrupt other cpu(s) */
588 cpu
= MSG_ALL_BUT_SELF
;
590 smp_send_xmon_break(cpu
);
594 if (!scanhex(&cpu
)) {
595 /* print cpus waiting or in xmon */
596 printf("cpus stopped:");
597 for (cpu
= 0; cpu
< NR_CPUS
; ++cpu
) {
598 if (test_bit(cpu
, &cpus_in_xmon
)) {
600 if (cpu
== smp_processor_id())
607 /* try to switch to cpu specified */
610 while (take_xmon
>= 0) {
611 if (--timeout
== 0) {
612 /* yes there's a race here */
614 printf("cpu %u didn't take control\n", cpu
);
618 /* now have to wait to be given control back */
619 while (test_and_set_bit(0, &got_xmon
)) {
620 if (take_xmon
== smp_processor_id()) {
626 #endif /* CONFIG_SMP */
628 #ifdef CONFIG_BOOTX_TEXT
629 extern boot_infos_t disp_bi
;
631 static void vidcmds(void)
635 extern int boot_text_mapped
;
637 if (!boot_text_mapped
)
639 if (c
!= '\n' && scanhex(&val
)) {
642 w
= disp_bi
.dispDeviceRowBytes
643 / (disp_bi
.dispDeviceDepth
>> 3);
644 disp_bi
.dispDeviceDepth
= val
;
645 disp_bi
.dispDeviceRowBytes
= w
* (val
>> 3);
648 disp_bi
.dispDeviceRowBytes
= val
;
651 disp_bi
.dispDeviceRect
[2] = val
;
654 disp_bi
.dispDeviceRect
[3] = val
;
658 printf("W = %d (0x%x) H = %d (0x%x) D = %d (0x%x) P = %d (0x%x)\n",
659 disp_bi
.dispDeviceRect
[2], disp_bi
.dispDeviceRect
[2],
660 disp_bi
.dispDeviceRect
[3], disp_bi
.dispDeviceRect
[3],
661 disp_bi
.dispDeviceDepth
, disp_bi
.dispDeviceDepth
,
662 disp_bi
.dispDeviceRowBytes
, disp_bi
.dispDeviceRowBytes
);
664 #endif /* CONFIG_BOOTX_TEXT */
666 static unsigned short fcstab
[256] = {
667 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
668 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
669 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
670 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
671 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
672 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
673 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
674 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
675 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
676 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
677 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
678 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
679 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
680 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
681 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
682 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
683 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
684 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
685 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
686 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
687 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
688 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
689 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
690 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
691 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
692 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
693 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
694 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
695 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
696 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
697 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
698 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
701 #define FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
712 if (!scanhex(&ncsum
))
715 for (i
= 0; i
< ncsum
; ++i
) {
716 if (mread(adrs
+i
, &v
, 1) == 0) {
717 printf("csum stopped at %x\n", adrs
+i
);
735 #if !defined(CONFIG_8xx)
752 dabr
.enabled
= scanhex(&dabr
.address
);
753 scanhex(&dabr
.count
);
755 dabr
.address
= (dabr
.address
& ~7) | mode
;
765 iabr
.enabled
= scanhex(&iabr
.address
);
767 iabr
.address
|= mode
;
768 scanhex(&iabr
.count
);
773 /* clear all breakpoints */
774 for (i
= 0; i
< NBPTS
; ++i
)
778 printf("All breakpoints cleared\n");
780 bp
= at_breakpoint(a
);
782 printf("No breakpoint at %x\n", a
);
791 /* print all breakpoints */
792 printf("type address count\n");
794 printf("data %.8x %8x [", dabr
.address
& ~7,
796 if (dabr
.address
& 1)
798 if (dabr
.address
& 2)
800 if (!(dabr
.address
& 4))
805 printf("inst %.8x %8x\n", iabr
.address
& ~3,
807 for (bp
= bpts
; bp
< &bpts
[NBPTS
]; ++bp
)
809 printf("trap %.8x %8x\n", bp
->address
,
813 bp
= at_breakpoint(a
);
815 for (bp
= bpts
; bp
< &bpts
[NBPTS
]; ++bp
)
818 if (bp
>= &bpts
[NBPTS
]) {
819 printf("Sorry, no free breakpoints\n");
832 backtrace(struct pt_regs
*excp
)
837 extern char ret_from_except
, ret_from_except_full
, ret_from_syscall
;
839 printf("backtrace:\n");
847 for (; sp
!= 0; sp
= stack
[0]) {
848 if (mread(sp
, stack
, sizeof(stack
)) != sizeof(stack
))
850 printf("[%.8lx] ", stack
);
851 xmon_print_symbol(stack
[1], " ", "\n");
852 if (stack
[1] == (unsigned) &ret_from_except
853 || stack
[1] == (unsigned) &ret_from_except_full
854 || stack
[1] == (unsigned) &ret_from_syscall
) {
855 if (mread(sp
+16, ®s
, sizeof(regs
)) != sizeof(regs
))
857 printf("exception:%x [%x] %x\n", regs
.trap
, sp
+16,
860 if (mread(sp
, stack
, sizeof(stack
)) != sizeof(stack
))
871 asm("mr %0,1" : "=r" (x
) :);
876 excprint(struct pt_regs
*fp
)
881 printf("cpu %d: ", smp_processor_id());
882 #endif /* CONFIG_SMP */
883 printf("vector: %x at pc=", fp
->trap
);
884 xmon_print_symbol(fp
->nip
, ": ", ", lr=");
885 xmon_print_symbol(fp
->link
, ": ", "\n");
886 printf("msr = %x, sp = %x [%x]\n", fp
->msr
, fp
->gpr
[1], fp
);
888 if (trap
== 0x300 || trap
== 0x600)
889 printf("dar = %x, dsisr = %x\n", fp
->dar
, fp
->dsisr
);
891 printf("current = %x, pid = %d, comm = %s\n",
892 current
, current
->pid
, current
->comm
);
896 prregs(struct pt_regs
*fp
)
902 fp
= (struct pt_regs
*) base
;
903 for (n
= 0; n
< 32; ++n
) {
904 printf("R%.2d = %.8x%s", n
, fp
->gpr
[n
],
905 (n
& 3) == 3? "\n": " ");
906 if (n
== 12 && !FULL_REGS(fp
)) {
911 printf("pc = %.8x msr = %.8x lr = %.8x cr = %.8x\n",
912 fp
->nip
, fp
->msr
, fp
->link
, fp
->ccr
);
913 printf("ctr = %.8x xer = %.8x trap = %4x\n",
914 fp
->ctr
, fp
->xer
, fp
->trap
);
931 nflush
= (nflush
+ 31) / 32;
933 for (; nflush
> 0; --nflush
, adrs
+= 0x20)
934 cflush((void *) adrs
);
936 for (; nflush
> 0; --nflush
, adrs
+= 0x20)
937 cinval((void *) adrs
);
944 unsigned int instrs
[2];
947 instrs
[0] = 0x7c6002a6 + ((n
& 0x1F) << 16) + ((n
& 0x3e0) << 6);
948 instrs
[1] = 0x4e800020;
950 store_inst(instrs
+1);
951 code
= (int (*)(void)) instrs
;
956 write_spr(int n
, unsigned int val
)
958 unsigned int instrs
[2];
959 int (*code
)(unsigned int);
961 instrs
[0] = 0x7c6003a6 + ((n
& 0x1F) << 16) + ((n
& 0x3e0) << 6);
962 instrs
[1] = 0x4e800020;
964 store_inst(instrs
+1);
965 code
= (int (*)(unsigned int)) instrs
;
969 static unsigned int regno
;
970 extern char exc_prolog
;
981 printf("msr = %x, pvr = %x\n", get_msr(), get_pvr());
982 printf("sprg0-3 = %x %x %x %x\n", get_sprg0(), get_sprg1(),
983 get_sprg2(), get_sprg3());
984 printf("srr0 = %x, srr1 = %x\n", get_srr0(), get_srr1());
985 #ifdef CONFIG_PPC_STD_MMU
987 for (i
= 0; i
< 16; ++i
)
988 printf(" %x", get_sr(i
));
991 asm("mr %0,1" : "=r" (i
) :);
992 printf("sp = %x ", i
);
993 asm("mr %0,2" : "=r" (i
) :);
994 printf("toc = %x\n", i
);
1001 val
= read_spr(regno
);
1003 write_spr(regno
, val
);
1006 printf("spr %x = %x\n", regno
, read_spr(regno
));
1009 val
= get_sr(regno
);
1022 #ifndef CONFIG_PPC_STD_MMU
1024 dump_hash_table(void)
1026 printf("This CPU doesn't have a hash table.\n");
1030 #ifndef CONFIG_PPC64BRIDGE
1032 dump_hash_table_seg(unsigned seg
, unsigned start
, unsigned end
)
1035 extern unsigned long Hash_size
;
1036 unsigned *htab
= Hash
;
1037 unsigned hsize
= Hash_size
;
1038 unsigned v
, hmask
, va
, last_va
= 0;
1039 int found
, last_found
, i
;
1040 unsigned *hg
, w1
, last_w2
= 0, last_va0
= 0;
1043 hmask
= hsize
/ 64 - 1;
1045 start
= (start
>> 12) & 0xffff;
1046 end
= (end
>> 12) & 0xffff;
1047 for (v
= start
; v
< end
; ++v
) {
1049 hg
= htab
+ (((v
^ seg
) & hmask
) * 16);
1050 w1
= 0x80000000 | (seg
<< 7) | (v
>> 10);
1051 for (i
= 0; i
< 8; ++i
, hg
+= 2) {
1059 hg
= htab
+ ((~(v
^ seg
) & hmask
) * 16);
1060 for (i
= 0; i
< 8; ++i
, hg
+= 2) {
1067 if (!(last_found
&& found
&& (hg
[1] & ~0x180) == last_w2
+ 4096)) {
1069 if (last_va
!= last_va0
)
1070 printf(" ... %x", last_va
);
1074 printf("%x to %x", va
, hg
[1]);
1080 last_w2
= hg
[1] & ~0x180;
1086 printf(" ... %x\n", last_va
);
1089 #else /* CONFIG_PPC64BRIDGE */
1091 dump_hash_table_seg(unsigned seg
, unsigned start
, unsigned end
)
1094 extern unsigned long Hash_size
;
1095 unsigned *htab
= Hash
;
1096 unsigned hsize
= Hash_size
;
1097 unsigned v
, hmask
, va
, last_va
;
1098 int found
, last_found
, i
;
1099 unsigned *hg
, w1
, last_w2
, last_va0
;
1102 hmask
= hsize
/ 128 - 1;
1104 start
= (start
>> 12) & 0xffff;
1105 end
= (end
>> 12) & 0xffff;
1106 for (v
= start
; v
< end
; ++v
) {
1108 hg
= htab
+ (((v
^ seg
) & hmask
) * 32);
1109 w1
= 1 | (seg
<< 12) | ((v
& 0xf800) >> 4);
1110 for (i
= 0; i
< 8; ++i
, hg
+= 4) {
1118 hg
= htab
+ ((~(v
^ seg
) & hmask
) * 32);
1119 for (i
= 0; i
< 8; ++i
, hg
+= 4) {
1126 if (!(last_found
&& found
&& (hg
[3] & ~0x180) == last_w2
+ 4096)) {
1128 if (last_va
!= last_va0
)
1129 printf(" ... %x", last_va
);
1133 printf("%x to %x", va
, hg
[3]);
1139 last_w2
= hg
[3] & ~0x180;
1145 printf(" ... %x\n", last_va
);
1147 #endif /* CONFIG_PPC64BRIDGE */
1149 static unsigned hash_ctx
;
1150 static unsigned hash_start
;
1151 static unsigned hash_end
;
1154 dump_hash_table(void)
1157 unsigned seg_start
, seg_end
;
1161 hash_end
= 0xfffff000;
1163 scanhex(&hash_start
);
1165 printf("Mappings for context %x\n", hash_ctx
);
1166 seg_start
= hash_start
;
1167 for (seg
= hash_start
>> 28; seg
<= hash_end
>> 28; ++seg
) {
1168 seg_end
= (seg
<< 28) | 0x0ffff000;
1169 if (seg_end
> hash_end
)
1171 dump_hash_table_seg((hash_ctx
<< 4) + (seg
* 0x111),
1172 seg_start
, seg_end
);
1173 seg_start
= seg_end
+ 0x1000;
1176 #endif /* CONFIG_PPC_STD_MMU */
1179 * Stuff for reading and writing memory safely
1183 mread(unsigned adrs
, void *buf
, int size
)
1189 if( setjmp(bus_error_jmp
) == 0 ){
1190 debugger_fault_handler
= handle_fault
;
1195 case 2: *(short *)q
= *(short *)p
; break;
1196 case 4: *(int *)q
= *(int *)p
; break;
1198 for( ; n
< size
; ++n
) {
1204 /* wait a little while to see if we get a machine check */
1208 debugger_fault_handler
= NULL
;
1213 mwrite(unsigned adrs
, void *buf
, int size
)
1219 if( setjmp(bus_error_jmp
) == 0 ){
1220 debugger_fault_handler
= handle_fault
;
1225 case 2: *(short *)p
= *(short *)q
; break;
1226 case 4: *(int *)p
= *(int *)q
; break;
1228 for( ; n
< size
; ++n
) {
1236 printf("*** Error writing address %x\n", adrs
+ n
);
1238 debugger_fault_handler
= NULL
;
1242 static int fault_type
;
1243 static int fault_except
;
1244 static char *fault_chars
[] = { "--", "**", "##" };
1247 handle_fault(struct pt_regs
*regs
)
1249 fault_except
= TRAP(regs
);
1250 fault_type
= TRAP(regs
) == 0x200? 0: TRAP(regs
) == 0x300? 1: 2;
1251 longjmp(bus_error_jmp
, 1);
1254 #define SWAP(a, b, t) ((t) = (a), (a) = (b), (b) = (t))
1257 byterev(unsigned char *val
, int size
)
1263 SWAP(val
[0], val
[1], t
);
1266 SWAP(val
[0], val
[3], t
);
1267 SWAP(val
[1], val
[2], t
);
1278 int cmd
, inc
, i
, nslash
;
1280 unsigned char val
[4];
1284 while ((cmd
= skipbl()) != '\n') {
1286 case 'b': size
= 1; break;
1287 case 'w': size
= 2; break;
1288 case 'l': size
= 4; break;
1289 case 'r': brev
= !brev
; break;
1290 case 'n': mnoread
= 1; break;
1291 case '.': mnoread
= 0; break;
1300 n
= mread(adrs
, val
, size
);
1301 printf("%.8x%c", adrs
, brev
? 'r': ' ');
1306 for (i
= 0; i
< n
; ++i
)
1307 printf("%.2x", val
[i
]);
1308 for (; i
< size
; ++i
)
1309 printf("%s", fault_chars
[fault_type
]);
1316 for (i
= 0; i
< size
; ++i
)
1317 val
[i
] = n
>> (i
* 8);
1320 mwrite(adrs
, val
, size
);
1333 else if( n
== '\'' )
1335 for (i
= 0; i
< size
; ++i
)
1336 val
[i
] = n
>> (i
* 8);
1339 mwrite(adrs
, val
, size
);
1373 adrs
-= 1 << nslash
;
1377 adrs
+= 1 << nslash
;
1381 adrs
+= 1 << -nslash
;
1385 adrs
-= 1 << -nslash
;
1419 case 'n': c
= '\n'; break;
1420 case 'r': c
= '\r'; break;
1421 case 'b': c
= '\b'; break;
1422 case 't': c
= '\t'; break;
1433 if ((isxdigit(c
) && c
!= 'f' && c
!= 'd') || c
== '\n')
1442 adrs
+= ppc_inst_dump(adrs
, nidump
);
1448 prdump(adrs
, ndump
);
1455 prdump(unsigned adrs
, int ndump
)
1457 register int n
, m
, c
, r
, nr
;
1458 unsigned char temp
[16];
1460 for( n
= ndump
; n
> 0; ){
1461 printf("%.8x", adrs
);
1464 nr
= mread(adrs
, temp
, r
);
1466 for( m
= 0; m
< r
; ++m
){
1467 putchar((m
& 3) == 0 && m
> 0? '.': ' ');
1469 printf("%.2x", temp
[m
]);
1471 printf("%s", fault_chars
[fault_type
]);
1476 for( m
= 0; m
< r
; ++m
){
1479 putchar(' ' <= c
&& c
<= '~'? c
: '.');
1493 ppc_inst_dump(unsigned adr
, int count
)
1497 unsigned long inst
, last_inst
= 0;
1498 unsigned char val
[4];
1501 for (first_adr
= adr
; count
> 0; --count
, adr
+= 4){
1502 nr
= mread(adr
, val
, 4);
1504 const char *x
= fault_chars
[fault_type
];
1505 printf("%.8x %s%s%s%s\n", adr
, x
, x
, x
, x
);
1508 inst
= GETWORD(val
);
1509 if (adr
> first_adr
&& inst
== last_inst
) {
1518 printf("%.8x ", adr
);
1519 printf("%.8x\t", inst
);
1520 print_insn_big_powerpc(stdout
, inst
, adr
); /* always returns 4 */
1523 return adr
- first_adr
;
1527 print_address(unsigned addr
)
1529 printf("0x%x", addr
);
1533 * Memory operations - move, set, print differences
1535 static unsigned mdest
; /* destination address */
1536 static unsigned msrc
; /* source address */
1537 static unsigned mval
; /* byte value to set memory to */
1538 static unsigned mcount
; /* # bytes to affect */
1539 static unsigned mdiffs
; /* max # differences to print */
1545 if( termch
!= '\n' )
1547 scanhex(cmd
== 's'? &mval
: &msrc
);
1548 if( termch
!= '\n' )
1553 memmove((void *)mdest
, (void *)msrc
, mcount
);
1556 memset((void *)mdest
, mval
, mcount
);
1559 if( termch
!= '\n' )
1562 memdiffs((unsigned char *)mdest
, (unsigned char *)msrc
, mcount
, mdiffs
);
1568 memdiffs(unsigned char *p1
, unsigned char *p2
, unsigned nb
, unsigned maxpr
)
1573 for( n
= nb
; n
> 0; --n
)
1574 if( *p1
++ != *p2
++ )
1575 if( ++prt
<= maxpr
)
1576 printf("%.8x %.2x # %.8x %.2x\n", (unsigned)p1
- 1,
1577 p1
[-1], (unsigned)p2
- 1, p2
[-1]);
1579 printf("Total of %d differences\n", prt
);
1582 static unsigned mend
;
1583 static unsigned mask
;
1589 unsigned char val
[4];
1593 if (termch
!= '\n') {
1596 if (termch
!= '\n') {
1600 if (termch
!= '\n') termch
= 0;
1605 for (a
= mdest
; a
< mend
; a
+= 4) {
1606 if (mread(a
, val
, 4) == 4
1607 && ((GETWORD(val
) ^ mval
) & mask
) == 0) {
1608 printf("%.8x: %.8x\n", a
, GETWORD(val
));
1615 static unsigned mskip
= 0x1000;
1616 static unsigned mlim
= 0xffffffff;
1626 if (termch
!= '\n') termch
= 0;
1628 if (termch
!= '\n') termch
= 0;
1631 for (a
= mdest
; a
< mlim
; a
+= mskip
) {
1632 ok
= mread(a
, &v
, 1);
1634 printf("%.8x .. ", a
);
1636 } else if (!ok
&& ook
)
1637 printf("%.8x\n", a
- mskip
);
1643 printf("%.8x\n", a
- mskip
);
1648 unsigned int args
[8];
1651 typedef unsigned int (*callfunc_t
)(unsigned int, unsigned int,
1652 unsigned int, unsigned int, unsigned int,
1653 unsigned int, unsigned int, unsigned int);
1659 for (i
= 0; i
< 8; ++i
)
1661 for (i
= 0; i
< 8; ++i
) {
1662 if (!scanhex(&args
[i
]) || termch
== '\n')
1666 func
= (callfunc_t
) adrs
;
1668 if (setjmp(bus_error_jmp
) == 0) {
1669 debugger_fault_handler
= handle_fault
;
1671 ret
= func(args
[0], args
[1], args
[2], args
[3],
1672 args
[4], args
[5], args
[6], args
[7]);
1674 printf("return value is %x\n", ret
);
1676 printf("*** %x exception occurred\n", fault_except
);
1678 debugger_fault_handler
= NULL
;
1681 /* Input scanning routines */
1692 while( c
== ' ' || c
== '\t' )
1698 static char *regnames
[N_PTREGS
] = {
1699 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
1700 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
1701 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
1702 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
1703 "pc", "msr", "or3", "ctr", "lr", "xer", "ccr", "mq",
1704 "trap", "dar", "dsisr", "res"
1708 scanhex(unsigned *vp
)
1715 /* parse register name */
1719 for (i
= 0; i
< sizeof(regname
) - 1; ++i
) {
1728 for (i
= 0; i
< N_PTREGS
; ++i
) {
1729 if (strcmp(regnames
[i
], regname
) == 0) {
1730 unsigned *rp
= (unsigned *)
1731 xmon_regs
[smp_processor_id()];
1733 printf("regs not available\n");
1740 printf("invalid register name '%%%s'\n", regname
);
1742 } else if (c
== '$') {
1743 static char symname
[128];
1745 for (i
=0; i
<63; i
++) {
1755 if (setjmp(bus_error_jmp
) == 0) {
1756 debugger_fault_handler
= handle_fault
;
1758 *vp
= kallsyms_lookup_name(symname
);
1761 debugger_fault_handler
= NULL
;
1763 printf("unknown symbol\n");
1779 } while( d
!= EOF
);
1798 if( '0' <= c
&& c
<= '9' )
1800 if( 'A' <= c
&& c
<= 'F' )
1801 return c
- ('A' - 10);
1802 if( 'a' <= c
&& c
<= 'f' )
1803 return c
- ('a' - 10);
1808 getstring(char *s
, int size
)
1819 } while( c
!= ' ' && c
!= '\t' && c
!= '\n' );
1824 static char line
[256];
1825 static char *lineptr
;
1836 if (lineptr
== NULL
|| *lineptr
== 0) {
1837 if (fgets(line
, sizeof(line
), stdin
) == NULL
) {
1847 take_input(char *str
)
1855 int type
= inchar();
1857 static char tmp
[128];
1862 xmon_print_symbol(addr
, ": ", "\n");
1867 if (setjmp(bus_error_jmp
) == 0) {
1868 debugger_fault_handler
= handle_fault
;
1870 addr
= kallsyms_lookup_name(tmp
);
1872 printf("%s: %lx\n", tmp
, addr
);
1874 printf("Symbol '%s' not found.\n", tmp
);
1877 debugger_fault_handler
= NULL
;