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 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\
154 p call function with arguments\n\
161 static int xmon_trace
[NR_CPUS
];
162 #define SSTEP 1 /* stepping because of 's' command */
163 #define BRSTEP 2 /* stepping over breakpoint */
165 static struct pt_regs
*xmon_regs
[NR_CPUS
];
167 extern inline void sync(void)
169 asm volatile("sync; isync");
172 extern inline void __delay(unsigned int loops
)
175 __asm__
__volatile__("mtctr %0; 1: bdnz 1b" : :
176 "r" (loops
) : "ctr");
179 /* Print an address in numeric and symbolic form (if possible) */
180 static void xmon_print_symbol(unsigned long address
, const char *mid
,
184 const char *name
= NULL
;
185 unsigned long offset
, size
;
186 static char tmpstr
[128];
188 printf("%.8lx", address
);
189 if (setjmp(bus_error_jmp
) == 0) {
190 debugger_fault_handler
= handle_fault
;
192 name
= kallsyms_lookup(address
, &size
, &offset
, &modname
,
195 /* wait a little while to see if we get a machine check */
198 debugger_fault_handler
= NULL
;
201 printf("%s%s+%#lx/%#lx", mid
, name
, offset
, size
);
203 printf(" [%s]", modname
);
208 static void get_tb(unsigned *p
)
210 unsigned hi
, lo
, hiagain
;
212 if ((get_pvr() >> 16) == 1)
216 asm volatile("mftbu %0; mftb %1; mftbu %2"
217 : "=r" (hi
), "=r" (lo
), "=r" (hiagain
));
218 } while (hi
!= hiagain
);
223 int xmon(struct pt_regs
*excp
)
228 get_tb(stop_tb
[smp_processor_id()]);
230 asm volatile ("stw 0,0(%0)\n\
233 stmw 2,8(%0)" : : "b" (®s
));
234 regs
.nip
= regs
.link
= ((unsigned long *)regs
.gpr
[1])[1];
235 regs
.msr
= get_msr();
236 regs
.ctr
= get_ctr();
237 regs
.xer
= get_xer();
244 set_msr(msr
& ~0x8000); /* disable interrupts */
245 xmon_regs
[smp_processor_id()] = excp
;
249 if (test_and_set_bit(smp_processor_id(), &cpus_in_xmon
))
252 while (test_and_set_bit(0, &got_xmon
)) {
253 if (take_xmon
== smp_processor_id()) {
259 * XXX: breakpoints are removed while any cpu is in xmon
261 #endif /* CONFIG_SMP */
263 #ifdef CONFIG_PMAC_BACKLIGHT
264 if( setjmp(bus_error_jmp
) == 0 ) {
265 debugger_fault_handler
= handle_fault
;
267 set_backlight_enable(1);
268 set_backlight_level(BACKLIGHT_MAX
);
271 debugger_fault_handler
= NULL
;
272 #endif /* CONFIG_PMAC_BACKLIGHT */
275 xmon_trace
[smp_processor_id()] = SSTEP
;
277 } else if (at_breakpoint(excp
->nip
)) {
278 xmon_trace
[smp_processor_id()] = BRSTEP
;
281 xmon_trace
[smp_processor_id()] = 0;
285 xmon_regs
[smp_processor_id()] = NULL
;
287 clear_bit(0, &got_xmon
);
288 clear_bit(smp_processor_id(), &cpus_in_xmon
);
289 #endif /* CONFIG_SMP */
290 set_msr(msr
); /* restore interrupt enable */
291 get_tb(start_tb
[smp_processor_id()]);
297 xmon_irq(int irq
, void *d
, struct pt_regs
*regs
)
300 local_irq_save(flags
);
301 printf("Keyboard interrupt\n");
303 local_irq_restore(flags
);
308 xmon_bpt(struct pt_regs
*regs
)
312 bp
= at_breakpoint(regs
->nip
);
319 xmon_trace
[smp_processor_id()] = BRSTEP
;
328 xmon_sstep(struct pt_regs
*regs
)
330 if (!xmon_trace
[smp_processor_id()])
332 if (xmon_trace
[smp_processor_id()] == BRSTEP
) {
333 xmon_trace
[smp_processor_id()] = 0;
342 xmon_dabr_match(struct pt_regs
*regs
)
344 if (dabr
.enabled
&& dabr
.count
) {
348 xmon_trace
[smp_processor_id()] = BRSTEP
;
351 dabr
.instr
= regs
->nip
;
358 xmon_iabr_match(struct pt_regs
*regs
)
360 if (iabr
.enabled
&& iabr
.count
) {
364 xmon_trace
[smp_processor_id()] = BRSTEP
;
373 at_breakpoint(unsigned pc
)
378 if (dabr
.enabled
&& pc
== dabr
.instr
)
380 if (iabr
.enabled
&& pc
== iabr
.address
)
383 for (i
= 0; i
< NBPTS
; ++i
, ++bp
)
384 if (bp
->enabled
&& pc
== bp
->address
)
396 for (i
= 0; i
< NBPTS
; ++i
, ++bp
) {
399 if (mread(bp
->address
, &bp
->instr
, 4) != 4
400 || mwrite(bp
->address
, &bpinstr
, 4) != 4) {
401 printf("Couldn't insert breakpoint at %x, disabling\n",
405 store_inst((void *) bp
->address
);
407 #if !defined(CONFIG_8xx)
409 set_dabr(dabr
.address
);
411 set_iabr(iabr
.address
);
422 #if !defined(CONFIG_8xx)
427 for (i
= 0; i
< NBPTS
; ++i
, ++bp
) {
430 if (mread(bp
->address
, &instr
, 4) == 4
432 && mwrite(bp
->address
, &bp
->instr
, 4) != 4)
433 printf("Couldn't remove breakpoint at %x\n",
435 store_inst((void *) bp
->address
);
439 static char *last_cmd
;
441 /* Command interpreting routine */
443 cmds(struct pt_regs
*excp
)
450 printf("%d:", smp_processor_id());
451 #endif /* CONFIG_SMP */
458 if (last_cmd
== NULL
)
460 take_input(last_cmd
);
492 prregs(excp
); /* print regs */
496 printf("No exception information\n");
520 printf("Unrecognized command: ");
521 if( ' ' < cmd
&& cmd
<= '~' )
524 printf("\\x%x", cmd
);
525 printf(" (type ? for help)\n");
537 #endif /* CONFIG_SMP */
538 #ifdef CONFIG_BOOTX_TEXT
556 extern unsigned tb_to_us
;
558 #define mulhwu(x,y) \
559 ({unsigned z; asm ("mulhwu %0,%1,%2" : "=r" (z) : "r" (x), "r" (y)); z;})
561 static void printtime(void)
565 delta
= stop_tb
[smp_processor_id()][1]
566 - start_tb
[smp_processor_id()][1];
567 delta
= mulhwu(tb_to_us
, delta
);
568 printf("%u.%06u seconds\n", delta
/ 1000000, delta
% 1000000);
571 static void bootcmds(void)
577 ppc_md
.restart(NULL
);
585 static void cpu_cmd(void)
593 /* interrupt other cpu(s) */
594 cpu
= MSG_ALL_BUT_SELF
;
596 smp_send_xmon_break(cpu
);
600 if (!scanhex(&cpu
)) {
601 /* print cpus waiting or in xmon */
602 printf("cpus stopped:");
603 for (cpu
= 0; cpu
< NR_CPUS
; ++cpu
) {
604 if (test_bit(cpu
, &cpus_in_xmon
)) {
606 if (cpu
== smp_processor_id())
613 /* try to switch to cpu specified */
616 while (take_xmon
>= 0) {
617 if (--timeout
== 0) {
618 /* yes there's a race here */
620 printf("cpu %u didn't take control\n", cpu
);
624 /* now have to wait to be given control back */
625 while (test_and_set_bit(0, &got_xmon
)) {
626 if (take_xmon
== smp_processor_id()) {
632 #endif /* CONFIG_SMP */
634 #ifdef CONFIG_BOOTX_TEXT
635 extern boot_infos_t disp_bi
;
637 static void vidcmds(void)
641 extern int boot_text_mapped
;
643 if (!boot_text_mapped
)
645 if (c
!= '\n' && scanhex(&val
)) {
648 w
= disp_bi
.dispDeviceRowBytes
649 / (disp_bi
.dispDeviceDepth
>> 3);
650 disp_bi
.dispDeviceDepth
= val
;
651 disp_bi
.dispDeviceRowBytes
= w
* (val
>> 3);
654 disp_bi
.dispDeviceRowBytes
= val
;
657 disp_bi
.dispDeviceRect
[2] = val
;
660 disp_bi
.dispDeviceRect
[3] = val
;
664 printf("W = %d (0x%x) H = %d (0x%x) D = %d (0x%x) P = %d (0x%x)\n",
665 disp_bi
.dispDeviceRect
[2], disp_bi
.dispDeviceRect
[2],
666 disp_bi
.dispDeviceRect
[3], disp_bi
.dispDeviceRect
[3],
667 disp_bi
.dispDeviceDepth
, disp_bi
.dispDeviceDepth
,
668 disp_bi
.dispDeviceRowBytes
, disp_bi
.dispDeviceRowBytes
);
670 #endif /* CONFIG_BOOTX_TEXT */
672 static unsigned short fcstab
[256] = {
673 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
674 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
675 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
676 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
677 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
678 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
679 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
680 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
681 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
682 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
683 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
684 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
685 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
686 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
687 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
688 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
689 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
690 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
691 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
692 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
693 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
694 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
695 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
696 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
697 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
698 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
699 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
700 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
701 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
702 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
703 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
704 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
707 #define FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
718 if (!scanhex(&ncsum
))
721 for (i
= 0; i
< ncsum
; ++i
) {
722 if (mread(adrs
+i
, &v
, 1) == 0) {
723 printf("csum stopped at %x\n", adrs
+i
);
741 #if !defined(CONFIG_8xx)
758 dabr
.enabled
= scanhex(&dabr
.address
);
759 scanhex(&dabr
.count
);
761 dabr
.address
= (dabr
.address
& ~7) | mode
;
771 iabr
.enabled
= scanhex(&iabr
.address
);
773 iabr
.address
|= mode
;
774 scanhex(&iabr
.count
);
779 /* clear all breakpoints */
780 for (i
= 0; i
< NBPTS
; ++i
)
784 printf("All breakpoints cleared\n");
786 bp
= at_breakpoint(a
);
788 printf("No breakpoint at %x\n", a
);
797 /* print all breakpoints */
798 printf("type address count\n");
800 printf("data %.8x %8x [", dabr
.address
& ~7,
802 if (dabr
.address
& 1)
804 if (dabr
.address
& 2)
806 if (!(dabr
.address
& 4))
811 printf("inst %.8x %8x\n", iabr
.address
& ~3,
813 for (bp
= bpts
; bp
< &bpts
[NBPTS
]; ++bp
)
815 printf("trap %.8x %8x\n", bp
->address
,
819 bp
= at_breakpoint(a
);
821 for (bp
= bpts
; bp
< &bpts
[NBPTS
]; ++bp
)
824 if (bp
>= &bpts
[NBPTS
]) {
825 printf("Sorry, no free breakpoints\n");
838 backtrace(struct pt_regs
*excp
)
843 extern char ret_from_except
, ret_from_except_full
, ret_from_syscall
;
845 printf("backtrace:\n");
853 for (; sp
!= 0; sp
= stack
[0]) {
854 if (mread(sp
, stack
, sizeof(stack
)) != sizeof(stack
))
856 printf("[%.8lx] ", stack
);
857 xmon_print_symbol(stack
[1], " ", "\n");
858 if (stack
[1] == (unsigned) &ret_from_except
859 || stack
[1] == (unsigned) &ret_from_except_full
860 || stack
[1] == (unsigned) &ret_from_syscall
) {
861 if (mread(sp
+16, ®s
, sizeof(regs
)) != sizeof(regs
))
863 printf("exception:%x [%x] %x\n", regs
.trap
, sp
+16,
866 if (mread(sp
, stack
, sizeof(stack
)) != sizeof(stack
))
877 asm("mr %0,1" : "=r" (x
) :);
882 excprint(struct pt_regs
*fp
)
887 printf("cpu %d: ", smp_processor_id());
888 #endif /* CONFIG_SMP */
889 printf("vector: %x at pc=", fp
->trap
);
890 xmon_print_symbol(fp
->nip
, ": ", ", lr=");
891 xmon_print_symbol(fp
->link
, ": ", "\n");
892 printf("msr = %x, sp = %x [%x]\n", fp
->msr
, fp
->gpr
[1], fp
);
894 if (trap
== 0x300 || trap
== 0x600)
895 printf("dar = %x, dsisr = %x\n", fp
->dar
, fp
->dsisr
);
897 printf("current = %x, pid = %d, comm = %s\n",
898 current
, current
->pid
, current
->comm
);
902 prregs(struct pt_regs
*fp
)
908 fp
= (struct pt_regs
*) base
;
909 for (n
= 0; n
< 32; ++n
) {
910 printf("R%.2d = %.8x%s", n
, fp
->gpr
[n
],
911 (n
& 3) == 3? "\n": " ");
912 if (n
== 12 && !FULL_REGS(fp
)) {
917 printf("pc = %.8x msr = %.8x lr = %.8x cr = %.8x\n",
918 fp
->nip
, fp
->msr
, fp
->link
, fp
->ccr
);
919 printf("ctr = %.8x xer = %.8x trap = %4x\n",
920 fp
->ctr
, fp
->xer
, fp
->trap
);
937 nflush
= (nflush
+ 31) / 32;
939 for (; nflush
> 0; --nflush
, adrs
+= 0x20)
940 cflush((void *) adrs
);
942 for (; nflush
> 0; --nflush
, adrs
+= 0x20)
943 cinval((void *) adrs
);
950 unsigned int instrs
[2];
953 instrs
[0] = 0x7c6002a6 + ((n
& 0x1F) << 16) + ((n
& 0x3e0) << 6);
954 instrs
[1] = 0x4e800020;
956 store_inst(instrs
+1);
957 code
= (int (*)(void)) instrs
;
962 write_spr(int n
, unsigned int val
)
964 unsigned int instrs
[2];
965 int (*code
)(unsigned int);
967 instrs
[0] = 0x7c6003a6 + ((n
& 0x1F) << 16) + ((n
& 0x3e0) << 6);
968 instrs
[1] = 0x4e800020;
970 store_inst(instrs
+1);
971 code
= (int (*)(unsigned int)) instrs
;
975 static unsigned int regno
;
976 extern char exc_prolog
;
987 printf("msr = %x, pvr = %x\n", get_msr(), get_pvr());
988 printf("sprg0-3 = %x %x %x %x\n", get_sprg0(), get_sprg1(),
989 get_sprg2(), get_sprg3());
990 printf("srr0 = %x, srr1 = %x\n", get_srr0(), get_srr1());
991 #ifdef CONFIG_PPC_STD_MMU
993 for (i
= 0; i
< 16; ++i
)
994 printf(" %x", get_sr(i
));
997 asm("mr %0,1" : "=r" (i
) :);
998 printf("sp = %x ", i
);
999 asm("mr %0,2" : "=r" (i
) :);
1000 printf("toc = %x\n", i
);
1007 val
= read_spr(regno
);
1009 write_spr(regno
, val
);
1012 printf("spr %x = %x\n", regno
, read_spr(regno
));
1015 val
= get_sr(regno
);
1028 #ifndef CONFIG_PPC_STD_MMU
1030 dump_hash_table(void)
1032 printf("This CPU doesn't have a hash table.\n");
1036 #ifndef CONFIG_PPC64BRIDGE
1038 dump_hash_table_seg(unsigned seg
, unsigned start
, unsigned end
)
1041 extern unsigned long Hash_size
;
1042 unsigned *htab
= Hash
;
1043 unsigned hsize
= Hash_size
;
1044 unsigned v
, hmask
, va
, last_va
= 0;
1045 int found
, last_found
, i
;
1046 unsigned *hg
, w1
, last_w2
= 0, last_va0
= 0;
1049 hmask
= hsize
/ 64 - 1;
1051 start
= (start
>> 12) & 0xffff;
1052 end
= (end
>> 12) & 0xffff;
1053 for (v
= start
; v
< end
; ++v
) {
1055 hg
= htab
+ (((v
^ seg
) & hmask
) * 16);
1056 w1
= 0x80000000 | (seg
<< 7) | (v
>> 10);
1057 for (i
= 0; i
< 8; ++i
, hg
+= 2) {
1065 hg
= htab
+ ((~(v
^ seg
) & hmask
) * 16);
1066 for (i
= 0; i
< 8; ++i
, hg
+= 2) {
1073 if (!(last_found
&& found
&& (hg
[1] & ~0x180) == last_w2
+ 4096)) {
1075 if (last_va
!= last_va0
)
1076 printf(" ... %x", last_va
);
1080 printf("%x to %x", va
, hg
[1]);
1086 last_w2
= hg
[1] & ~0x180;
1092 printf(" ... %x\n", last_va
);
1095 #else /* CONFIG_PPC64BRIDGE */
1097 dump_hash_table_seg(unsigned seg
, unsigned start
, unsigned end
)
1100 extern unsigned long Hash_size
;
1101 unsigned *htab
= Hash
;
1102 unsigned hsize
= Hash_size
;
1103 unsigned v
, hmask
, va
, last_va
;
1104 int found
, last_found
, i
;
1105 unsigned *hg
, w1
, last_w2
, last_va0
;
1108 hmask
= hsize
/ 128 - 1;
1110 start
= (start
>> 12) & 0xffff;
1111 end
= (end
>> 12) & 0xffff;
1112 for (v
= start
; v
< end
; ++v
) {
1114 hg
= htab
+ (((v
^ seg
) & hmask
) * 32);
1115 w1
= 1 | (seg
<< 12) | ((v
& 0xf800) >> 4);
1116 for (i
= 0; i
< 8; ++i
, hg
+= 4) {
1124 hg
= htab
+ ((~(v
^ seg
) & hmask
) * 32);
1125 for (i
= 0; i
< 8; ++i
, hg
+= 4) {
1132 if (!(last_found
&& found
&& (hg
[3] & ~0x180) == last_w2
+ 4096)) {
1134 if (last_va
!= last_va0
)
1135 printf(" ... %x", last_va
);
1139 printf("%x to %x", va
, hg
[3]);
1145 last_w2
= hg
[3] & ~0x180;
1151 printf(" ... %x\n", last_va
);
1153 #endif /* CONFIG_PPC64BRIDGE */
1155 static unsigned hash_ctx
;
1156 static unsigned hash_start
;
1157 static unsigned hash_end
;
1160 dump_hash_table(void)
1163 unsigned seg_start
, seg_end
;
1167 hash_end
= 0xfffff000;
1169 scanhex(&hash_start
);
1171 printf("Mappings for context %x\n", hash_ctx
);
1172 seg_start
= hash_start
;
1173 for (seg
= hash_start
>> 28; seg
<= hash_end
>> 28; ++seg
) {
1174 seg_end
= (seg
<< 28) | 0x0ffff000;
1175 if (seg_end
> hash_end
)
1177 dump_hash_table_seg((hash_ctx
<< 4) + (seg
* 0x111),
1178 seg_start
, seg_end
);
1179 seg_start
= seg_end
+ 0x1000;
1182 #endif /* CONFIG_PPC_STD_MMU */
1185 * Stuff for reading and writing memory safely
1189 mread(unsigned adrs
, void *buf
, int size
)
1195 if( setjmp(bus_error_jmp
) == 0 ){
1196 debugger_fault_handler
= handle_fault
;
1201 case 2: *(short *)q
= *(short *)p
; break;
1202 case 4: *(int *)q
= *(int *)p
; break;
1204 for( ; n
< size
; ++n
) {
1210 /* wait a little while to see if we get a machine check */
1214 debugger_fault_handler
= NULL
;
1219 mwrite(unsigned adrs
, void *buf
, int size
)
1225 if( setjmp(bus_error_jmp
) == 0 ){
1226 debugger_fault_handler
= handle_fault
;
1231 case 2: *(short *)p
= *(short *)q
; break;
1232 case 4: *(int *)p
= *(int *)q
; break;
1234 for( ; n
< size
; ++n
) {
1242 printf("*** Error writing address %x\n", adrs
+ n
);
1244 debugger_fault_handler
= NULL
;
1248 static int fault_type
;
1249 static int fault_except
;
1250 static char *fault_chars
[] = { "--", "**", "##" };
1253 handle_fault(struct pt_regs
*regs
)
1255 fault_except
= TRAP(regs
);
1256 fault_type
= TRAP(regs
) == 0x200? 0: TRAP(regs
) == 0x300? 1: 2;
1257 longjmp(bus_error_jmp
, 1);
1260 #define SWAP(a, b, t) ((t) = (a), (a) = (b), (b) = (t))
1263 byterev(unsigned char *val
, int size
)
1269 SWAP(val
[0], val
[1], t
);
1272 SWAP(val
[0], val
[3], t
);
1273 SWAP(val
[1], val
[2], t
);
1284 int cmd
, inc
, i
, nslash
;
1286 unsigned char val
[4];
1290 while ((cmd
= skipbl()) != '\n') {
1292 case 'b': size
= 1; break;
1293 case 'w': size
= 2; break;
1294 case 'l': size
= 4; break;
1295 case 'r': brev
= !brev
; break;
1296 case 'n': mnoread
= 1; break;
1297 case '.': mnoread
= 0; break;
1306 n
= mread(adrs
, val
, size
);
1307 printf("%.8x%c", adrs
, brev
? 'r': ' ');
1312 for (i
= 0; i
< n
; ++i
)
1313 printf("%.2x", val
[i
]);
1314 for (; i
< size
; ++i
)
1315 printf("%s", fault_chars
[fault_type
]);
1322 for (i
= 0; i
< size
; ++i
)
1323 val
[i
] = n
>> (i
* 8);
1326 mwrite(adrs
, val
, size
);
1339 else if( n
== '\'' )
1341 for (i
= 0; i
< size
; ++i
)
1342 val
[i
] = n
>> (i
* 8);
1345 mwrite(adrs
, val
, size
);
1379 adrs
-= 1 << nslash
;
1383 adrs
+= 1 << nslash
;
1387 adrs
+= 1 << -nslash
;
1391 adrs
-= 1 << -nslash
;
1425 case 'n': c
= '\n'; break;
1426 case 'r': c
= '\r'; break;
1427 case 'b': c
= '\b'; break;
1428 case 't': c
= '\t'; break;
1439 if ((isxdigit(c
) && c
!= 'f' && c
!= 'd') || c
== '\n')
1448 adrs
+= ppc_inst_dump(adrs
, nidump
);
1454 prdump(adrs
, ndump
);
1461 prdump(unsigned adrs
, int ndump
)
1463 register int n
, m
, c
, r
, nr
;
1464 unsigned char temp
[16];
1466 for( n
= ndump
; n
> 0; ){
1467 printf("%.8x", adrs
);
1470 nr
= mread(adrs
, temp
, r
);
1472 for( m
= 0; m
< r
; ++m
){
1473 putchar((m
& 3) == 0 && m
> 0? '.': ' ');
1475 printf("%.2x", temp
[m
]);
1477 printf("%s", fault_chars
[fault_type
]);
1482 for( m
= 0; m
< r
; ++m
){
1485 putchar(' ' <= c
&& c
<= '~'? c
: '.');
1499 ppc_inst_dump(unsigned adr
, int count
)
1503 unsigned long inst
, last_inst
= 0;
1504 unsigned char val
[4];
1507 for (first_adr
= adr
; count
> 0; --count
, adr
+= 4){
1508 nr
= mread(adr
, val
, 4);
1510 const char *x
= fault_chars
[fault_type
];
1511 printf("%.8x %s%s%s%s\n", adr
, x
, x
, x
, x
);
1514 inst
= GETWORD(val
);
1515 if (adr
> first_adr
&& inst
== last_inst
) {
1524 printf("%.8x ", adr
);
1525 printf("%.8x\t", inst
);
1526 print_insn_big_powerpc(stdout
, inst
, adr
); /* always returns 4 */
1529 return adr
- first_adr
;
1533 print_address(unsigned addr
)
1535 printf("0x%x", addr
);
1539 * Memory operations - move, set, print differences
1541 static unsigned mdest
; /* destination address */
1542 static unsigned msrc
; /* source address */
1543 static unsigned mval
; /* byte value to set memory to */
1544 static unsigned mcount
; /* # bytes to affect */
1545 static unsigned mdiffs
; /* max # differences to print */
1551 if( termch
!= '\n' )
1553 scanhex(cmd
== 's'? &mval
: &msrc
);
1554 if( termch
!= '\n' )
1559 memmove((void *)mdest
, (void *)msrc
, mcount
);
1562 memset((void *)mdest
, mval
, mcount
);
1565 if( termch
!= '\n' )
1568 memdiffs((unsigned char *)mdest
, (unsigned char *)msrc
, mcount
, mdiffs
);
1574 memdiffs(unsigned char *p1
, unsigned char *p2
, unsigned nb
, unsigned maxpr
)
1579 for( n
= nb
; n
> 0; --n
)
1580 if( *p1
++ != *p2
++ )
1581 if( ++prt
<= maxpr
)
1582 printf("%.8x %.2x # %.8x %.2x\n", (unsigned)p1
- 1,
1583 p1
[-1], (unsigned)p2
- 1, p2
[-1]);
1585 printf("Total of %d differences\n", prt
);
1588 static unsigned mend
;
1589 static unsigned mask
;
1595 unsigned char val
[4];
1599 if (termch
!= '\n') {
1602 if (termch
!= '\n') {
1606 if (termch
!= '\n') termch
= 0;
1611 for (a
= mdest
; a
< mend
; a
+= 4) {
1612 if (mread(a
, val
, 4) == 4
1613 && ((GETWORD(val
) ^ mval
) & mask
) == 0) {
1614 printf("%.8x: %.8x\n", a
, GETWORD(val
));
1621 static unsigned mskip
= 0x1000;
1622 static unsigned mlim
= 0xffffffff;
1632 if (termch
!= '\n') termch
= 0;
1634 if (termch
!= '\n') termch
= 0;
1637 for (a
= mdest
; a
< mlim
; a
+= mskip
) {
1638 ok
= mread(a
, &v
, 1);
1640 printf("%.8x .. ", a
);
1642 } else if (!ok
&& ook
)
1643 printf("%.8x\n", a
- mskip
);
1649 printf("%.8x\n", a
- mskip
);
1654 unsigned int args
[8];
1657 typedef unsigned int (*callfunc_t
)(unsigned int, unsigned int,
1658 unsigned int, unsigned int, unsigned int,
1659 unsigned int, unsigned int, unsigned int);
1665 for (i
= 0; i
< 8; ++i
)
1667 for (i
= 0; i
< 8; ++i
) {
1668 if (!scanhex(&args
[i
]) || termch
== '\n')
1672 func
= (callfunc_t
) adrs
;
1674 if (setjmp(bus_error_jmp
) == 0) {
1675 debugger_fault_handler
= handle_fault
;
1677 ret
= func(args
[0], args
[1], args
[2], args
[3],
1678 args
[4], args
[5], args
[6], args
[7]);
1680 printf("return value is %x\n", ret
);
1682 printf("*** %x exception occurred\n", fault_except
);
1684 debugger_fault_handler
= NULL
;
1687 /* Input scanning routines */
1698 while( c
== ' ' || c
== '\t' )
1704 static char *regnames
[N_PTREGS
] = {
1705 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
1706 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
1707 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
1708 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
1709 "pc", "msr", "or3", "ctr", "lr", "xer", "ccr", "mq",
1710 "trap", "dar", "dsisr", "res"
1714 scanhex(unsigned *vp
)
1721 /* parse register name */
1725 for (i
= 0; i
< sizeof(regname
) - 1; ++i
) {
1734 for (i
= 0; i
< N_PTREGS
; ++i
) {
1735 if (strcmp(regnames
[i
], regname
) == 0) {
1736 unsigned *rp
= (unsigned *)
1737 xmon_regs
[smp_processor_id()];
1739 printf("regs not available\n");
1746 printf("invalid register name '%%%s'\n", regname
);
1748 } else if (c
== '$') {
1749 static char symname
[128];
1751 for (i
=0; i
<63; i
++) {
1761 if (setjmp(bus_error_jmp
) == 0) {
1762 debugger_fault_handler
= handle_fault
;
1764 *vp
= kallsyms_lookup_name(symname
);
1767 debugger_fault_handler
= NULL
;
1769 printf("unknown symbol\n");
1785 } while( d
!= EOF
);
1804 if( '0' <= c
&& c
<= '9' )
1806 if( 'A' <= c
&& c
<= 'F' )
1807 return c
- ('A' - 10);
1808 if( 'a' <= c
&& c
<= 'f' )
1809 return c
- ('a' - 10);
1814 getstring(char *s
, int size
)
1825 } while( c
!= ' ' && c
!= '\t' && c
!= '\n' );
1830 static char line
[256];
1831 static char *lineptr
;
1842 if (lineptr
== NULL
|| *lineptr
== 0) {
1843 if (fgets(line
, sizeof(line
), stdin
) == NULL
) {
1853 take_input(char *str
)
1861 int type
= inchar();
1863 static char tmp
[128];
1868 xmon_print_symbol(addr
, ": ", "\n");
1873 if (setjmp(bus_error_jmp
) == 0) {
1874 debugger_fault_handler
= handle_fault
;
1876 addr
= kallsyms_lookup_name(tmp
);
1878 printf("%s: %lx\n", tmp
, addr
);
1880 printf("Symbol '%s' not found.\n", tmp
);
1883 debugger_fault_handler
= NULL
;