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 <asm/ptrace.h>
13 #include <asm/string.h>
15 #include <asm/bootx.h>
16 #include <asm/machdep.h>
18 #ifdef CONFIG_PMAC_BACKLIGHT
19 #include <asm/backlight.h>
24 #define scanhex xmon_scanhex
25 #define skipbl xmon_skipbl
28 static unsigned long cpus_in_xmon
= 0;
29 static unsigned long got_xmon
= 0;
30 static volatile int take_xmon
= -1;
31 #endif /* CONFIG_SMP */
35 static unsigned ndump
= 64;
36 static unsigned nidump
= 16;
37 static unsigned ncsum
= 4096;
40 static u_int bus_error_jmp
[100];
41 #define setjmp xmon_setjmp
42 #define longjmp xmon_longjmp
44 /* Breakpoint stuff */
49 unsigned char enabled
;
53 static struct bpt bpts
[NBPTS
];
54 static struct bpt dabr
;
55 static struct bpt iabr
;
56 static unsigned bpinstr
= 0x7fe00008; /* trap */
59 extern void (*debugger_fault_handler
)(struct pt_regs
*);
60 static int cmds(struct pt_regs
*);
61 static int mread(unsigned, void *, int);
62 static int mwrite(unsigned, void *, int);
63 static void handle_fault(struct pt_regs
*);
64 static void byterev(unsigned char *, int);
65 static void memex(void);
66 static int bsesc(void);
67 static void dump(void);
68 static void prdump(unsigned, int);
70 static void prndump(unsigned, int);
71 static int nvreadb(unsigned);
73 static int ppc_inst_dump(unsigned, int);
74 void print_address(unsigned);
75 static int getsp(void);
76 static void dump_hash_table(void);
77 static void backtrace(struct pt_regs
*);
78 static void excprint(struct pt_regs
*);
79 static void prregs(struct pt_regs
*);
80 static void memops(int);
81 static void memlocate(void);
82 static void memzcan(void);
83 static void memdiffs(unsigned char *, unsigned char *, unsigned, unsigned);
85 int scanhex(unsigned *valp
);
86 static void scannl(void);
87 static int hexdigit(int);
88 void getstring(char *, int);
89 static void flush_input(void);
90 static int inchar(void);
91 static void take_input(char *);
92 /* static void openforth(void); */
93 static unsigned read_spr(int);
94 static void write_spr(int, unsigned);
95 static void super_regs(void);
96 static void print_sysmap(void);
97 static void sysmap_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 int pretty_print_addr(unsigned long addr
);
107 static void csum(void);
108 #ifdef CONFIG_BOOTX_TEXT
109 static void vidcmds(void);
111 static void bootcmds(void);
112 static void proccall(void);
113 static void printtime(void);
115 extern int print_insn_big_powerpc(FILE *, unsigned long, unsigned);
116 extern void printf(const char *fmt
, ...);
117 extern int putchar(int ch
);
118 extern int setjmp(u_int
*);
119 extern void longjmp(u_int
*, int);
121 extern void xmon_enter(void);
122 extern void xmon_leave(void);
123 extern char* xmon_find_symbol(unsigned long addr
, unsigned long* saddr
);
124 extern unsigned long xmon_symbol_to_addr(char* symbol
);
126 static unsigned start_tb
[NR_CPUS
][2];
127 static unsigned stop_tb
[NR_CPUS
][2];
129 #define GETWORD(v) (((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
131 #define isxdigit(c) (('0' <= (c) && (c) <= '9') \
132 || ('a' <= (c) && (c) <= 'f') \
133 || ('A' <= (c) && (c) <= 'F'))
134 #define isalnum(c) (('0' <= (c) && (c) <= '9') \
135 || ('a' <= (c) && (c) <= 'z') \
136 || ('A' <= (c) && (c) <= 'Z'))
137 #define isspace(c) (c == ' ' || c == '\t' || c == 10 || c == 13 || c == 0)
139 static char *help_string
= "\
142 di dump instructions\n\
143 df dump float values\n\
144 dd dump double values\n\
145 e print exception information\n\
147 m examine/change memory\n\
148 mm move a block of memory\n\
149 ms set a block of memory\n\
150 md compare two blocks of memory\n\
151 M print System.map\n\
153 S print special registers\n\
155 la lookup address in system.map\n\
156 ls lookup symbol in system.map\n\
160 static int xmon_trace
[NR_CPUS
];
161 #define SSTEP 1 /* stepping because of 's' command */
162 #define BRSTEP 2 /* stepping over breakpoint */
164 static struct pt_regs
*xmon_regs
[NR_CPUS
];
166 extern inline void sync(void)
168 asm volatile("sync; isync");
171 extern inline void __delay(unsigned int loops
)
174 __asm__
__volatile__("mtctr %0; 1: bdnz 1b" : :
175 "r" (loops
) : "ctr");
178 static void get_tb(unsigned *p
)
180 unsigned hi
, lo
, hiagain
;
182 if ((get_pvr() >> 16) == 1)
186 asm volatile("mftbu %0; mftb %1; mftbu %2"
187 : "=r" (hi
), "=r" (lo
), "=r" (hiagain
));
188 } while (hi
!= hiagain
);
194 xmon(struct pt_regs
*excp
)
199 get_tb(stop_tb
[smp_processor_id()]);
201 asm volatile ("stw 0,0(%0)\n\
204 stmw 2,8(%0)" : : "b" (®s
));
205 regs
.nip
= regs
.link
= ((unsigned long *)regs
.gpr
[1])[1];
206 regs
.msr
= get_msr();
207 regs
.ctr
= get_ctr();
208 regs
.xer
= get_xer();
215 set_msr(msr
& ~0x8000); /* disable interrupts */
216 xmon_regs
[smp_processor_id()] = excp
;
220 if (test_and_set_bit(smp_processor_id(), &cpus_in_xmon
))
223 while (test_and_set_bit(0, &got_xmon
)) {
224 if (take_xmon
== smp_processor_id()) {
230 * XXX: breakpoints are removed while any cpu is in xmon
232 #endif /* CONFIG_SMP */
234 #ifdef CONFIG_PMAC_BACKLIGHT
235 if( setjmp(bus_error_jmp
) == 0 ) {
236 debugger_fault_handler
= handle_fault
;
238 set_backlight_enable(1);
239 set_backlight_level(BACKLIGHT_MAX
);
242 debugger_fault_handler
= NULL
;
243 #endif /* CONFIG_PMAC_BACKLIGHT */
246 xmon_trace
[smp_processor_id()] = SSTEP
;
248 } else if (at_breakpoint(excp
->nip
)) {
249 xmon_trace
[smp_processor_id()] = BRSTEP
;
252 xmon_trace
[smp_processor_id()] = 0;
256 xmon_regs
[smp_processor_id()] = NULL
;
258 clear_bit(0, &got_xmon
);
259 clear_bit(smp_processor_id(), &cpus_in_xmon
);
260 #endif /* CONFIG_SMP */
261 set_msr(msr
); /* restore interrupt enable */
262 get_tb(start_tb
[smp_processor_id()]);
266 xmon_irq(int irq
, void *d
, struct pt_regs
*regs
)
269 local_irq_save(flags
);
270 printf("Keyboard interrupt\n");
272 local_irq_restore(flags
);
277 xmon_bpt(struct pt_regs
*regs
)
281 bp
= at_breakpoint(regs
->nip
);
288 xmon_trace
[smp_processor_id()] = BRSTEP
;
297 xmon_sstep(struct pt_regs
*regs
)
299 if (!xmon_trace
[smp_processor_id()])
301 if (xmon_trace
[smp_processor_id()] == BRSTEP
) {
302 xmon_trace
[smp_processor_id()] = 0;
311 xmon_dabr_match(struct pt_regs
*regs
)
313 if (dabr
.enabled
&& dabr
.count
) {
317 xmon_trace
[smp_processor_id()] = BRSTEP
;
320 dabr
.instr
= regs
->nip
;
327 xmon_iabr_match(struct pt_regs
*regs
)
329 if (iabr
.enabled
&& iabr
.count
) {
333 xmon_trace
[smp_processor_id()] = BRSTEP
;
342 at_breakpoint(unsigned pc
)
347 if (dabr
.enabled
&& pc
== dabr
.instr
)
349 if (iabr
.enabled
&& pc
== iabr
.address
)
352 for (i
= 0; i
< NBPTS
; ++i
, ++bp
)
353 if (bp
->enabled
&& pc
== bp
->address
)
365 for (i
= 0; i
< NBPTS
; ++i
, ++bp
) {
368 if (mread(bp
->address
, &bp
->instr
, 4) != 4
369 || mwrite(bp
->address
, &bpinstr
, 4) != 4) {
370 printf("Couldn't insert breakpoint at %x, disabling\n",
374 store_inst((void *) bp
->address
);
376 #if !defined(CONFIG_8xx)
378 set_dabr(dabr
.address
);
380 set_iabr(iabr
.address
);
391 #if !defined(CONFIG_8xx)
396 for (i
= 0; i
< NBPTS
; ++i
, ++bp
) {
399 if (mread(bp
->address
, &instr
, 4) == 4
401 && mwrite(bp
->address
, &bp
->instr
, 4) != 4)
402 printf("Couldn't remove breakpoint at %x\n",
404 store_inst((void *) bp
->address
);
408 static char *last_cmd
;
410 /* Command interpreting routine */
412 cmds(struct pt_regs
*excp
)
419 printf("%d:", smp_processor_id());
420 #endif /* CONFIG_SMP */
427 if (last_cmd
== NULL
)
429 take_input(last_cmd
);
461 prregs(excp
); /* print regs */
465 printf("No exception information\n");
492 printf("Unrecognized command: ");
493 if( ' ' < cmd
&& cmd
<= '~' )
496 printf("\\x%x", cmd
);
497 printf(" (type ? for help)\n");
509 #endif /* CONFIG_SMP */
510 #ifdef CONFIG_BOOTX_TEXT
528 extern unsigned tb_to_us
;
530 #define mulhwu(x,y) \
531 ({unsigned z; asm ("mulhwu %0,%1,%2" : "=r" (z) : "r" (x), "r" (y)); z;})
533 static void printtime(void)
537 delta
= stop_tb
[smp_processor_id()][1]
538 - start_tb
[smp_processor_id()][1];
539 delta
= mulhwu(tb_to_us
, delta
);
540 printf("%u.%06u seconds\n", delta
/ 1000000, delta
% 1000000);
543 static void bootcmds(void)
549 ppc_md
.restart(NULL
);
557 static void cpu_cmd(void)
565 /* interrupt other cpu(s) */
566 cpu
= MSG_ALL_BUT_SELF
;
568 smp_send_xmon_break(cpu
);
572 if (!scanhex(&cpu
)) {
573 /* print cpus waiting or in xmon */
574 printf("cpus stopped:");
575 for (cpu
= 0; cpu
< NR_CPUS
; ++cpu
) {
576 if (test_bit(cpu
, &cpus_in_xmon
)) {
578 if (cpu
== smp_processor_id())
585 /* try to switch to cpu specified */
588 while (take_xmon
>= 0) {
589 if (--timeout
== 0) {
590 /* yes there's a race here */
592 printf("cpu %u didn't take control\n", cpu
);
596 /* now have to wait to be given control back */
597 while (test_and_set_bit(0, &got_xmon
)) {
598 if (take_xmon
== smp_processor_id()) {
604 #endif /* CONFIG_SMP */
606 #ifdef CONFIG_BOOTX_TEXT
607 extern boot_infos_t disp_bi
;
609 static void vidcmds(void)
613 extern int boot_text_mapped
;
615 if (!boot_text_mapped
)
617 if (c
!= '\n' && scanhex(&val
)) {
620 w
= disp_bi
.dispDeviceRowBytes
621 / (disp_bi
.dispDeviceDepth
>> 3);
622 disp_bi
.dispDeviceDepth
= val
;
623 disp_bi
.dispDeviceRowBytes
= w
* (val
>> 3);
626 disp_bi
.dispDeviceRowBytes
= val
;
629 disp_bi
.dispDeviceRect
[2] = val
;
632 disp_bi
.dispDeviceRect
[3] = val
;
636 printf("W = %d (0x%x) H = %d (0x%x) D = %d (0x%x) P = %d (0x%x)\n",
637 disp_bi
.dispDeviceRect
[2], disp_bi
.dispDeviceRect
[2],
638 disp_bi
.dispDeviceRect
[3], disp_bi
.dispDeviceRect
[3],
639 disp_bi
.dispDeviceDepth
, disp_bi
.dispDeviceDepth
,
640 disp_bi
.dispDeviceRowBytes
, disp_bi
.dispDeviceRowBytes
);
642 #endif /* CONFIG_BOOTX_TEXT */
644 static unsigned short fcstab
[256] = {
645 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
646 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
647 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
648 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
649 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
650 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
651 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
652 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
653 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
654 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
655 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
656 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
657 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
658 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
659 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
660 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
661 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
662 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
663 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
664 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
665 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
666 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
667 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
668 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
669 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
670 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
671 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
672 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
673 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
674 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
675 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
676 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
679 #define FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
690 if (!scanhex(&ncsum
))
693 for (i
= 0; i
< ncsum
; ++i
) {
694 if (mread(adrs
+i
, &v
, 1) == 0) {
695 printf("csum stopped at %x\n", adrs
+i
);
713 #if !defined(CONFIG_8xx)
730 dabr
.enabled
= scanhex(&dabr
.address
);
731 scanhex(&dabr
.count
);
733 dabr
.address
= (dabr
.address
& ~7) | mode
;
743 iabr
.enabled
= scanhex(&iabr
.address
);
745 iabr
.address
|= mode
;
746 scanhex(&iabr
.count
);
751 /* clear all breakpoints */
752 for (i
= 0; i
< NBPTS
; ++i
)
756 printf("All breakpoints cleared\n");
758 bp
= at_breakpoint(a
);
760 printf("No breakpoint at %x\n", a
);
769 /* print all breakpoints */
770 printf("type address count\n");
772 printf("data %.8x %8x [", dabr
.address
& ~7,
774 if (dabr
.address
& 1)
776 if (dabr
.address
& 2)
778 if (!(dabr
.address
& 4))
783 printf("inst %.8x %8x\n", iabr
.address
& ~3,
785 for (bp
= bpts
; bp
< &bpts
[NBPTS
]; ++bp
)
787 printf("trap %.8x %8x\n", bp
->address
,
791 bp
= at_breakpoint(a
);
793 for (bp
= bpts
; bp
< &bpts
[NBPTS
]; ++bp
)
796 if (bp
>= &bpts
[NBPTS
]) {
797 printf("Sorry, no free breakpoints\n");
810 backtrace(struct pt_regs
*excp
)
815 extern char ret_from_except
, ret_from_except_full
, ret_from_syscall
;
817 printf("backtrace:\n");
825 for (; sp
!= 0; sp
= stack
[0]) {
826 if (mread(sp
, stack
, sizeof(stack
)) != sizeof(stack
))
828 pretty_print_addr(stack
[1]);
830 if (stack
[1] == (unsigned) &ret_from_except
831 || stack
[1] == (unsigned) &ret_from_except_full
832 || stack
[1] == (unsigned) &ret_from_syscall
) {
833 if (mread(sp
+16, ®s
, sizeof(regs
)) != sizeof(regs
))
835 printf("\nexception:%x [%x] %x ", regs
.trap
, sp
+16,
838 if (mread(sp
, stack
, sizeof(stack
)) != sizeof(stack
))
850 asm("mr %0,1" : "=r" (x
) :);
855 excprint(struct pt_regs
*fp
)
860 printf("cpu %d: ", smp_processor_id());
861 #endif /* CONFIG_SMP */
862 printf("vector: %x at pc = ", fp
->trap
);
863 pretty_print_addr(fp
->nip
);
865 pretty_print_addr(fp
->link
);
866 printf("\nmsr = %x, sp = %x [%x]\n", fp
->msr
, fp
->gpr
[1], fp
);
868 if (trap
== 0x300 || trap
== 0x600)
869 printf("dar = %x, dsisr = %x\n", fp
->dar
, fp
->dsisr
);
871 printf("current = %x, pid = %d, comm = %s\n",
872 current
, current
->pid
, current
->comm
);
876 prregs(struct pt_regs
*fp
)
882 fp
= (struct pt_regs
*) base
;
883 for (n
= 0; n
< 32; ++n
) {
884 printf("R%.2d = %.8x%s", n
, fp
->gpr
[n
],
885 (n
& 3) == 3? "\n": " ");
886 if (n
== 12 && !FULL_REGS(fp
)) {
891 printf("pc = %.8x msr = %.8x lr = %.8x cr = %.8x\n",
892 fp
->nip
, fp
->msr
, fp
->link
, fp
->ccr
);
893 printf("ctr = %.8x xer = %.8x trap = %4x\n",
894 fp
->ctr
, fp
->xer
, fp
->trap
);
911 nflush
= (nflush
+ 31) / 32;
913 for (; nflush
> 0; --nflush
, adrs
+= 0x20)
914 cflush((void *) adrs
);
916 for (; nflush
> 0; --nflush
, adrs
+= 0x20)
917 cinval((void *) adrs
);
924 unsigned int instrs
[2];
927 instrs
[0] = 0x7c6002a6 + ((n
& 0x1F) << 16) + ((n
& 0x3e0) << 6);
928 instrs
[1] = 0x4e800020;
930 store_inst(instrs
+1);
931 code
= (int (*)(void)) instrs
;
936 write_spr(int n
, unsigned int val
)
938 unsigned int instrs
[2];
939 int (*code
)(unsigned int);
941 instrs
[0] = 0x7c6003a6 + ((n
& 0x1F) << 16) + ((n
& 0x3e0) << 6);
942 instrs
[1] = 0x4e800020;
944 store_inst(instrs
+1);
945 code
= (int (*)(unsigned int)) instrs
;
949 static unsigned int regno
;
950 extern char exc_prolog
;
958 printf("System.map: \n");
959 if( setjmp(bus_error_jmp
) == 0 ) {
960 debugger_fault_handler
= handle_fault
;
965 debugger_fault_handler
= NULL
;
968 printf("No System.map\n");
979 printf("msr = %x, pvr = %x\n", get_msr(), get_pvr());
980 printf("sprg0-3 = %x %x %x %x\n", get_sprg0(), get_sprg1(),
981 get_sprg2(), get_sprg3());
982 printf("srr0 = %x, srr1 = %x\n", get_srr0(), get_srr1());
983 #ifdef CONFIG_PPC_STD_MMU
985 for (i
= 0; i
< 16; ++i
)
986 printf(" %x", get_sr(i
));
989 asm("mr %0,1" : "=r" (i
) :);
990 printf("sp = %x ", i
);
991 asm("mr %0,2" : "=r" (i
) :);
992 printf("toc = %x\n", i
);
999 val
= read_spr(regno
);
1001 write_spr(regno
, val
);
1004 printf("spr %x = %x\n", regno
, read_spr(regno
));
1007 val
= get_sr(regno
);
1020 #ifndef CONFIG_PPC_STD_MMU
1022 dump_hash_table(void)
1024 printf("This CPU doesn't have a hash table.\n");
1028 #ifndef CONFIG_PPC64BRIDGE
1030 dump_hash_table_seg(unsigned seg
, unsigned start
, unsigned end
)
1033 extern unsigned long Hash_size
;
1034 unsigned *htab
= Hash
;
1035 unsigned hsize
= Hash_size
;
1036 unsigned v
, hmask
, va
, last_va
= 0;
1037 int found
, last_found
, i
;
1038 unsigned *hg
, w1
, last_w2
= 0, last_va0
= 0;
1041 hmask
= hsize
/ 64 - 1;
1043 start
= (start
>> 12) & 0xffff;
1044 end
= (end
>> 12) & 0xffff;
1045 for (v
= start
; v
< end
; ++v
) {
1047 hg
= htab
+ (((v
^ seg
) & hmask
) * 16);
1048 w1
= 0x80000000 | (seg
<< 7) | (v
>> 10);
1049 for (i
= 0; i
< 8; ++i
, hg
+= 2) {
1057 hg
= htab
+ ((~(v
^ seg
) & hmask
) * 16);
1058 for (i
= 0; i
< 8; ++i
, hg
+= 2) {
1065 if (!(last_found
&& found
&& (hg
[1] & ~0x180) == last_w2
+ 4096)) {
1067 if (last_va
!= last_va0
)
1068 printf(" ... %x", last_va
);
1072 printf("%x to %x", va
, hg
[1]);
1078 last_w2
= hg
[1] & ~0x180;
1084 printf(" ... %x\n", last_va
);
1087 #else /* CONFIG_PPC64BRIDGE */
1089 dump_hash_table_seg(unsigned seg
, unsigned start
, unsigned end
)
1092 extern unsigned long Hash_size
;
1093 unsigned *htab
= Hash
;
1094 unsigned hsize
= Hash_size
;
1095 unsigned v
, hmask
, va
, last_va
;
1096 int found
, last_found
, i
;
1097 unsigned *hg
, w1
, last_w2
, last_va0
;
1100 hmask
= hsize
/ 128 - 1;
1102 start
= (start
>> 12) & 0xffff;
1103 end
= (end
>> 12) & 0xffff;
1104 for (v
= start
; v
< end
; ++v
) {
1106 hg
= htab
+ (((v
^ seg
) & hmask
) * 32);
1107 w1
= 1 | (seg
<< 12) | ((v
& 0xf800) >> 4);
1108 for (i
= 0; i
< 8; ++i
, hg
+= 4) {
1116 hg
= htab
+ ((~(v
^ seg
) & hmask
) * 32);
1117 for (i
= 0; i
< 8; ++i
, hg
+= 4) {
1124 if (!(last_found
&& found
&& (hg
[3] & ~0x180) == last_w2
+ 4096)) {
1126 if (last_va
!= last_va0
)
1127 printf(" ... %x", last_va
);
1131 printf("%x to %x", va
, hg
[3]);
1137 last_w2
= hg
[3] & ~0x180;
1143 printf(" ... %x\n", last_va
);
1145 #endif /* CONFIG_PPC64BRIDGE */
1147 static unsigned hash_ctx
;
1148 static unsigned hash_start
;
1149 static unsigned hash_end
;
1152 dump_hash_table(void)
1155 unsigned seg_start
, seg_end
;
1159 hash_end
= 0xfffff000;
1161 scanhex(&hash_start
);
1163 printf("Mappings for context %x\n", hash_ctx
);
1164 seg_start
= hash_start
;
1165 for (seg
= hash_start
>> 28; seg
<= hash_end
>> 28; ++seg
) {
1166 seg_end
= (seg
<< 28) | 0x0ffff000;
1167 if (seg_end
> hash_end
)
1169 dump_hash_table_seg((hash_ctx
<< 4) + (seg
* 0x111),
1170 seg_start
, seg_end
);
1171 seg_start
= seg_end
+ 0x1000;
1174 #endif /* CONFIG_PPC_STD_MMU */
1177 * Stuff for reading and writing memory safely
1181 mread(unsigned adrs
, void *buf
, int size
)
1187 if( setjmp(bus_error_jmp
) == 0 ){
1188 debugger_fault_handler
= handle_fault
;
1193 case 2: *(short *)q
= *(short *)p
; break;
1194 case 4: *(int *)q
= *(int *)p
; break;
1196 for( ; n
< size
; ++n
) {
1202 /* wait a little while to see if we get a machine check */
1206 debugger_fault_handler
= NULL
;
1211 mwrite(unsigned adrs
, void *buf
, int size
)
1217 if( setjmp(bus_error_jmp
) == 0 ){
1218 debugger_fault_handler
= handle_fault
;
1223 case 2: *(short *)p
= *(short *)q
; break;
1224 case 4: *(int *)p
= *(int *)q
; break;
1226 for( ; n
< size
; ++n
) {
1234 printf("*** Error writing address %x\n", adrs
+ n
);
1236 debugger_fault_handler
= NULL
;
1240 static int fault_type
;
1241 static int fault_except
;
1242 static char *fault_chars
[] = { "--", "**", "##" };
1245 handle_fault(struct pt_regs
*regs
)
1247 fault_except
= TRAP(regs
);
1248 fault_type
= TRAP(regs
) == 0x200? 0: TRAP(regs
) == 0x300? 1: 2;
1249 longjmp(bus_error_jmp
, 1);
1252 #define SWAP(a, b, t) ((t) = (a), (a) = (b), (b) = (t))
1255 byterev(unsigned char *val
, int size
)
1261 SWAP(val
[0], val
[1], t
);
1264 SWAP(val
[0], val
[3], t
);
1265 SWAP(val
[1], val
[2], t
);
1276 int cmd
, inc
, i
, nslash
;
1278 unsigned char val
[4];
1282 while ((cmd
= skipbl()) != '\n') {
1284 case 'b': size
= 1; break;
1285 case 'w': size
= 2; break;
1286 case 'l': size
= 4; break;
1287 case 'r': brev
= !brev
; break;
1288 case 'n': mnoread
= 1; break;
1289 case '.': mnoread
= 0; break;
1298 n
= mread(adrs
, val
, size
);
1299 printf("%.8x%c", adrs
, brev
? 'r': ' ');
1304 for (i
= 0; i
< n
; ++i
)
1305 printf("%.2x", val
[i
]);
1306 for (; i
< size
; ++i
)
1307 printf("%s", fault_chars
[fault_type
]);
1314 for (i
= 0; i
< size
; ++i
)
1315 val
[i
] = n
>> (i
* 8);
1318 mwrite(adrs
, val
, size
);
1331 else if( n
== '\'' )
1333 for (i
= 0; i
< size
; ++i
)
1334 val
[i
] = n
>> (i
* 8);
1337 mwrite(adrs
, val
, size
);
1371 adrs
-= 1 << nslash
;
1375 adrs
+= 1 << nslash
;
1379 adrs
+= 1 << -nslash
;
1383 adrs
-= 1 << -nslash
;
1417 case 'n': c
= '\n'; break;
1418 case 'r': c
= '\r'; break;
1419 case 'b': c
= '\b'; break;
1420 case 't': c
= '\t'; break;
1431 if ((isxdigit(c
) && c
!= 'f' && c
!= 'd') || c
== '\n')
1440 adrs
+= ppc_inst_dump(adrs
, nidump
);
1446 prdump(adrs
, ndump
);
1453 prdump(unsigned adrs
, int ndump
)
1455 register int n
, m
, c
, r
, nr
;
1456 unsigned char temp
[16];
1458 for( n
= ndump
; n
> 0; ){
1459 printf("%.8x", adrs
);
1462 nr
= mread(adrs
, temp
, r
);
1464 for( m
= 0; m
< r
; ++m
){
1465 putchar((m
& 3) == 0 && m
> 0? '.': ' ');
1467 printf("%.2x", temp
[m
]);
1469 printf("%s", fault_chars
[fault_type
]);
1474 for( m
= 0; m
< r
; ++m
){
1477 putchar(' ' <= c
&& c
<= '~'? c
: '.');
1491 ppc_inst_dump(unsigned adr
, int count
)
1495 unsigned long inst
, last_inst
= 0;
1496 unsigned char val
[4];
1499 for (first_adr
= adr
; count
> 0; --count
, adr
+= 4){
1500 nr
= mread(adr
, val
, 4);
1502 const char *x
= fault_chars
[fault_type
];
1503 printf("%.8x %s%s%s%s\n", adr
, x
, x
, x
, x
);
1506 inst
= GETWORD(val
);
1507 if (adr
> first_adr
&& inst
== last_inst
) {
1516 printf("%.8x ", adr
);
1517 printf("%.8x\t", inst
);
1518 print_insn_big_powerpc(stdout
, inst
, adr
); /* always returns 4 */
1521 return adr
- first_adr
;
1525 print_address(unsigned addr
)
1527 printf("0x%x", addr
);
1531 * Memory operations - move, set, print differences
1533 static unsigned mdest
; /* destination address */
1534 static unsigned msrc
; /* source address */
1535 static unsigned mval
; /* byte value to set memory to */
1536 static unsigned mcount
; /* # bytes to affect */
1537 static unsigned mdiffs
; /* max # differences to print */
1543 if( termch
!= '\n' )
1545 scanhex(cmd
== 's'? &mval
: &msrc
);
1546 if( termch
!= '\n' )
1551 memmove((void *)mdest
, (void *)msrc
, mcount
);
1554 memset((void *)mdest
, mval
, mcount
);
1557 if( termch
!= '\n' )
1560 memdiffs((unsigned char *)mdest
, (unsigned char *)msrc
, mcount
, mdiffs
);
1566 memdiffs(unsigned char *p1
, unsigned char *p2
, unsigned nb
, unsigned maxpr
)
1571 for( n
= nb
; n
> 0; --n
)
1572 if( *p1
++ != *p2
++ )
1573 if( ++prt
<= maxpr
)
1574 printf("%.8x %.2x # %.8x %.2x\n", (unsigned)p1
- 1,
1575 p1
[-1], (unsigned)p2
- 1, p2
[-1]);
1577 printf("Total of %d differences\n", prt
);
1580 static unsigned mend
;
1581 static unsigned mask
;
1587 unsigned char val
[4];
1591 if (termch
!= '\n') {
1594 if (termch
!= '\n') {
1598 if (termch
!= '\n') termch
= 0;
1603 for (a
= mdest
; a
< mend
; a
+= 4) {
1604 if (mread(a
, val
, 4) == 4
1605 && ((GETWORD(val
) ^ mval
) & mask
) == 0) {
1606 printf("%.8x: %.8x\n", a
, GETWORD(val
));
1613 static unsigned mskip
= 0x1000;
1614 static unsigned mlim
= 0xffffffff;
1624 if (termch
!= '\n') termch
= 0;
1626 if (termch
!= '\n') termch
= 0;
1629 for (a
= mdest
; a
< mlim
; a
+= mskip
) {
1630 ok
= mread(a
, &v
, 1);
1632 printf("%.8x .. ", a
);
1634 } else if (!ok
&& ook
)
1635 printf("%.8x\n", a
- mskip
);
1641 printf("%.8x\n", a
- mskip
);
1646 unsigned int args
[8];
1649 typedef unsigned int (*callfunc_t
)(unsigned int, unsigned int,
1650 unsigned int, unsigned int, unsigned int,
1651 unsigned int, unsigned int, unsigned int);
1657 for (i
= 0; i
< 8; ++i
)
1659 for (i
= 0; i
< 8; ++i
) {
1660 if (!scanhex(&args
[i
]) || termch
== '\n')
1664 func
= (callfunc_t
) adrs
;
1666 if (setjmp(bus_error_jmp
) == 0) {
1667 debugger_fault_handler
= handle_fault
;
1669 ret
= func(args
[0], args
[1], args
[2], args
[3],
1670 args
[4], args
[5], args
[6], args
[7]);
1672 printf("return value is %x\n", ret
);
1674 printf("*** %x exception occurred\n", fault_except
);
1676 debugger_fault_handler
= NULL
;
1679 /* Input scanning routines */
1690 while( c
== ' ' || c
== '\t' )
1696 static char *regnames
[N_PTREGS
] = {
1697 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
1698 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
1699 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
1700 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
1701 "pc", "msr", "or3", "ctr", "lr", "xer", "ccr", "mq",
1702 "trap", "dar", "dsisr", "res"
1706 scanhex(unsigned *vp
)
1713 /* parse register name */
1717 for (i
= 0; i
< sizeof(regname
) - 1; ++i
) {
1726 for (i
= 0; i
< N_PTREGS
; ++i
) {
1727 if (strcmp(regnames
[i
], regname
) == 0) {
1728 unsigned *rp
= (unsigned *)
1729 xmon_regs
[smp_processor_id()];
1731 printf("regs not available\n");
1738 printf("invalid register name '%%%s'\n", regname
);
1740 } else if (c
== '$') {
1741 static char symname
[64];
1743 for (i
=0; i
<63; i
++) {
1752 *vp
= xmon_symbol_to_addr(symname
);
1754 printf("unknown symbol\n");
1770 } while( d
!= EOF
);
1789 if( '0' <= c
&& c
<= '9' )
1791 if( 'A' <= c
&& c
<= 'F' )
1792 return c
- ('A' - 10);
1793 if( 'a' <= c
&& c
<= 'f' )
1794 return c
- ('a' - 10);
1799 getstring(char *s
, int size
)
1810 } while( c
!= ' ' && c
!= '\t' && c
!= '\n' );
1815 static char line
[256];
1816 static char *lineptr
;
1827 if (lineptr
== NULL
|| *lineptr
== 0) {
1828 if (fgets(line
, sizeof(line
), stdin
) == NULL
) {
1838 take_input(char *str
)
1846 int type
= inchar();
1848 static char tmp
[64];
1851 extern char *sysmap
;
1852 extern unsigned long sysmap_size
;
1853 if ( !sysmap
|| !sysmap_size
)
1858 if (scanhex(&addr
)) {
1859 pretty_print_addr(addr
);
1866 if( setjmp(bus_error_jmp
) == 0 ) {
1867 debugger_fault_handler
= handle_fault
;
1871 cur
= strstr(cur
, tmp
);
1873 static char res
[64];
1876 while(p
> sysmap
&& *p
!= 10)
1880 while(*p
&& p
< (sysmap
+ sysmap_size
) && *p
!= 10)
1883 printf("%s\n", res
);
1889 debugger_fault_handler
= NULL
;
1896 pretty_print_addr(unsigned long addr
)
1899 unsigned long saddr
;
1901 printf("%08x", addr
);
1902 sym
= xmon_find_symbol(addr
, &saddr
);
1904 printf(" (%s+0x%x)", sym
, addr
-saddr
);
1909 xmon_find_symbol(unsigned long addr
, unsigned long* saddr
)
1911 static char rbuffer
[64];
1912 char *p
, *ep
, *limit
;
1913 unsigned long prev
, next
;
1916 extern char *sysmap
;
1917 extern unsigned long sysmap_size
;
1918 if ( !sysmap
|| !sysmap_size
)
1924 limit
= p
+ sysmap_size
;
1925 if( setjmp(bus_error_jmp
) == 0 ) {
1926 debugger_fault_handler
= handle_fault
;
1929 next
= simple_strtoul(p
, &p
, 16);
1930 if (next
> addr
&& prev
<= addr
) {
1935 while(*p
&& p
< limit
&& *p
== 32)
1937 while(*p
&& p
< limit
&& *p
!= 10 && (ep
- rbuffer
) < 63)
1942 debugger_fault_handler
= NULL
;
1947 while(*p
&& p
< limit
&& *p
!= 10)
1950 } while(*p
&& p
< limit
&& next
);
1954 debugger_fault_handler
= NULL
;
1959 xmon_symbol_to_addr(char* symbol
)
1966 extern char *sysmap
;
1967 extern unsigned long sysmap_size
;
1968 if ( !sysmap
|| !sysmap_size
)
1971 if( setjmp(bus_error_jmp
) == 0 ) {
1972 debugger_fault_handler
= handle_fault
;
1976 cur
= strstr(cur
, symbol
);
1980 /* best match if equal, better match if
1983 if (cur
== sysmap
|| *(cur
-1) == ' ') {
1985 if (cur
[strlen(symbol
)] == 10)
1988 if (gd
> goodness
) {
1999 while(p
> sysmap
&& *p
!= 10)
2002 result
= simple_strtoul(p
, &p
, 16);
2006 debugger_fault_handler
= NULL
;