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>
22 #define scanhex xmon_scanhex
23 #define skipbl xmon_skipbl
26 static unsigned long cpus_in_xmon = 0;
27 static unsigned long got_xmon = 0;
28 static volatile int take_xmon = -1;
29 #endif /* CONFIG_SMP */
33 static unsigned ndump = 64;
34 static unsigned nidump = 16;
35 static unsigned ncsum = 4096;
38 static u_int bus_error_jmp[100];
39 #define setjmp xmon_setjmp
40 #define longjmp xmon_longjmp
42 /* Breakpoint stuff */
47 unsigned char enabled;
51 static struct bpt bpts[NBPTS];
52 static struct bpt dabr;
53 static struct bpt iabr;
54 static unsigned bpinstr = 0x7fe00008; /* trap */
57 extern void (*debugger_fault_handler)(struct pt_regs *);
58 static int cmds(struct pt_regs *);
59 static int mread(unsigned, void *, int);
60 static int mwrite(unsigned, void *, int);
61 static void handle_fault(struct pt_regs *);
62 static void byterev(unsigned char *, int);
63 static void memex(void);
64 static int bsesc(void);
65 static void dump(void);
66 static void prdump(unsigned, int);
68 static void prndump(unsigned, int);
69 static int nvreadb(unsigned);
71 static int ppc_inst_dump(unsigned, int);
72 void print_address(unsigned);
73 static int getsp(void);
74 static void dump_hash_table(void);
75 static void backtrace(struct pt_regs *);
76 static void excprint(struct pt_regs *);
77 static void prregs(struct pt_regs *);
78 static void memops(int);
79 static void memlocate(void);
80 static void memzcan(void);
81 static void memdiffs(unsigned char *, unsigned char *, unsigned, unsigned);
83 int scanhex(unsigned *valp);
84 static void scannl(void);
85 static int hexdigit(int);
86 void getstring(char *, int);
87 static void flush_input(void);
88 static int inchar(void);
89 static void take_input(char *);
90 /* static void openforth(void); */
91 static unsigned read_spr(int);
92 static void write_spr(int, unsigned);
93 static void super_regs(void);
94 static void symbol_lookup(void);
95 static void remove_bpts(void);
96 static void insert_bpts(void);
97 static struct bpt *at_breakpoint(unsigned pc);
98 static void bpt_cmds(void);
99 void cacheflush(void);
101 static void cpu_cmd(void);
102 #endif /* CONFIG_SMP */
103 static void csum(void);
104 #ifdef CONFIG_BOOTX_TEXT
105 static void vidcmds(void);
107 static void bootcmds(void);
108 static void proccall(void);
109 static void printtime(void);
111 extern int print_insn_big_powerpc(FILE *, unsigned long, unsigned);
112 extern void printf(const char *fmt, ...);
113 extern int putchar(int ch);
114 extern int setjmp(u_int *);
115 extern void longjmp(u_int *, int);
117 extern void xmon_enter(void);
118 extern void xmon_leave(void);
120 static unsigned start_tb[NR_CPUS][2];
121 static unsigned stop_tb[NR_CPUS][2];
123 #define GETWORD(v) (((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
125 #define isxdigit(c) (('0' <= (c) && (c) <= '9') \
126 || ('a' <= (c) && (c) <= 'f') \
127 || ('A' <= (c) && (c) <= 'F'))
128 #define isalnum(c) (('0' <= (c) && (c) <= '9') \
129 || ('a' <= (c) && (c) <= 'z') \
130 || ('A' <= (c) && (c) <= 'Z'))
131 #define isspace(c) (c == ' ' || c == '\t' || c == 10 || c == 13 || c == 0)
133 static char *help_string = "\
136 di dump instructions\n\
137 df dump float values\n\
138 dd dump double values\n\
139 e print exception information\n\
141 m examine/change memory\n\
142 mm move a block of memory\n\
143 ms set a block of memory\n\
144 md compare two blocks of memory\n\
146 S print special registers\n\
151 p call function with arguments\n\
158 static int xmon_trace[NR_CPUS];
159 #define SSTEP 1 /* stepping because of 's' command */
160 #define BRSTEP 2 /* stepping over breakpoint */
162 static struct pt_regs *xmon_regs[NR_CPUS];
164 extern inline void sync(void)
166 asm volatile("sync; isync");
169 extern inline void __delay(unsigned int loops)
172 __asm__ __volatile__("mtctr %0; 1: bdnz 1b" : :
173 "r" (loops) : "ctr");
176 /* Print an address in numeric and symbolic form (if possible) */
177 static void xmon_print_symbol(unsigned long address, const char *mid,
181 const char *name = NULL;
182 unsigned long offset, size;
183 static char tmpstr[128];
185 printf("%.8lx", address);
186 if (setjmp(bus_error_jmp) == 0) {
187 debugger_fault_handler = handle_fault;
189 name = kallsyms_lookup(address, &size, &offset, &modname,
192 /* wait a little while to see if we get a machine check */
195 debugger_fault_handler = NULL;
198 printf("%s%s+%#lx/%#lx", mid, name, offset, size);
200 printf(" [%s]", modname);
205 static void get_tb(unsigned *p)
207 unsigned hi, lo, hiagain;
209 if ((get_pvr() >> 16) == 1)
213 asm volatile("mftbu %0; mftb %1; mftbu %2"
214 : "=r" (hi), "=r" (lo), "=r" (hiagain));
215 } while (hi != hiagain);
220 int xmon(struct pt_regs *excp)
225 get_tb(stop_tb[smp_processor_id()]);
227 asm volatile ("stw 0,0(%0)\n\
230 stmw 2,8(%0)" : : "b" (®s));
231 regs.nip = regs.link = ((unsigned long *)regs.gpr[1])[1];
232 regs.msr = get_msr();
233 regs.ctr = get_ctr();
234 regs.xer = get_xer();
241 set_msr(msr & ~0x8000); /* disable interrupts */
242 xmon_regs[smp_processor_id()] = excp;
246 if (test_and_set_bit(smp_processor_id(), &cpus_in_xmon))
249 while (test_and_set_bit(0, &got_xmon)) {
250 if (take_xmon == smp_processor_id()) {
256 * XXX: breakpoints are removed while any cpu is in xmon
258 #endif /* CONFIG_SMP */
262 xmon_trace[smp_processor_id()] = SSTEP;
264 } else if (at_breakpoint(excp->nip)) {
265 xmon_trace[smp_processor_id()] = BRSTEP;
268 xmon_trace[smp_processor_id()] = 0;
272 xmon_regs[smp_processor_id()] = NULL;
274 clear_bit(0, &got_xmon);
275 clear_bit(smp_processor_id(), &cpus_in_xmon);
276 #endif /* CONFIG_SMP */
277 set_msr(msr); /* restore interrupt enable */
278 get_tb(start_tb[smp_processor_id()]);
284 xmon_irq(int irq, void *d, struct pt_regs *regs)
287 local_irq_save(flags);
288 printf("Keyboard interrupt\n");
290 local_irq_restore(flags);
295 xmon_bpt(struct pt_regs *regs)
299 bp = at_breakpoint(regs->nip);
306 xmon_trace[smp_processor_id()] = BRSTEP;
315 xmon_sstep(struct pt_regs *regs)
317 if (!xmon_trace[smp_processor_id()])
319 if (xmon_trace[smp_processor_id()] == BRSTEP) {
320 xmon_trace[smp_processor_id()] = 0;
329 xmon_dabr_match(struct pt_regs *regs)
331 if (dabr.enabled && dabr.count) {
335 xmon_trace[smp_processor_id()] = BRSTEP;
338 dabr.instr = regs->nip;
345 xmon_iabr_match(struct pt_regs *regs)
347 if (iabr.enabled && iabr.count) {
351 xmon_trace[smp_processor_id()] = BRSTEP;
360 at_breakpoint(unsigned pc)
365 if (dabr.enabled && pc == dabr.instr)
367 if (iabr.enabled && pc == iabr.address)
370 for (i = 0; i < NBPTS; ++i, ++bp)
371 if (bp->enabled && pc == bp->address)
383 for (i = 0; i < NBPTS; ++i, ++bp) {
386 if (mread(bp->address, &bp->instr, 4) != 4
387 || mwrite(bp->address, &bpinstr, 4) != 4) {
388 printf("Couldn't insert breakpoint at %x, disabling\n",
392 store_inst((void *) bp->address);
394 #if !defined(CONFIG_8xx)
396 set_dabr(dabr.address);
398 set_iabr(iabr.address);
409 #if !defined(CONFIG_8xx)
414 for (i = 0; i < NBPTS; ++i, ++bp) {
417 if (mread(bp->address, &instr, 4) == 4
419 && mwrite(bp->address, &bp->instr, 4) != 4)
420 printf("Couldn't remove breakpoint at %x\n",
422 store_inst((void *) bp->address);
426 static char *last_cmd;
428 /* Command interpreting routine */
430 cmds(struct pt_regs *excp)
437 printf("%d:", smp_processor_id());
438 #endif /* CONFIG_SMP */
445 if (last_cmd == NULL)
447 take_input(last_cmd);
479 prregs(excp); /* print regs */
483 printf("No exception information\n");
507 printf("Unrecognized command: ");
508 if( ' ' < cmd && cmd <= '~' )
511 printf("\\x%x", cmd);
512 printf(" (type ? for help)\n");
524 #endif /* CONFIG_SMP */
525 #ifdef CONFIG_BOOTX_TEXT
543 extern unsigned tb_to_us;
545 #define mulhwu(x,y) \
546 ({unsigned z; asm ("mulhwu %0,%1,%2" : "=r" (z) : "r" (x), "r" (y)); z;})
548 static void printtime(void)
552 delta = stop_tb[smp_processor_id()][1]
553 - start_tb[smp_processor_id()][1];
554 delta = mulhwu(tb_to_us, delta);
555 printf("%u.%06u seconds\n", delta / 1000000, delta % 1000000);
558 static void bootcmds(void)
564 ppc_md.restart(NULL);
572 static void cpu_cmd(void)
580 /* interrupt other cpu(s) */
581 cpu = MSG_ALL_BUT_SELF;
583 smp_send_xmon_break(cpu);
587 if (!scanhex(&cpu)) {
588 /* print cpus waiting or in xmon */
589 printf("cpus stopped:");
590 for (cpu = 0; cpu < NR_CPUS; ++cpu) {
591 if (test_bit(cpu, &cpus_in_xmon)) {
593 if (cpu == smp_processor_id())
600 /* try to switch to cpu specified */
603 while (take_xmon >= 0) {
604 if (--timeout == 0) {
605 /* yes there's a race here */
607 printf("cpu %u didn't take control\n", cpu);
611 /* now have to wait to be given control back */
612 while (test_and_set_bit(0, &got_xmon)) {
613 if (take_xmon == smp_processor_id()) {
619 #endif /* CONFIG_SMP */
621 #ifdef CONFIG_BOOTX_TEXT
622 extern boot_infos_t disp_bi;
624 static void vidcmds(void)
628 extern int boot_text_mapped;
630 if (!boot_text_mapped)
632 if (c != '\n' && scanhex(&val)) {
635 w = disp_bi.dispDeviceRowBytes
636 / (disp_bi.dispDeviceDepth >> 3);
637 disp_bi.dispDeviceDepth = val;
638 disp_bi.dispDeviceRowBytes = w * (val >> 3);
641 disp_bi.dispDeviceRowBytes = val;
644 disp_bi.dispDeviceRect[2] = val;
647 disp_bi.dispDeviceRect[3] = val;
651 printf("W = %d (0x%x) H = %d (0x%x) D = %d (0x%x) P = %d (0x%x)\n",
652 disp_bi.dispDeviceRect[2], disp_bi.dispDeviceRect[2],
653 disp_bi.dispDeviceRect[3], disp_bi.dispDeviceRect[3],
654 disp_bi.dispDeviceDepth, disp_bi.dispDeviceDepth,
655 disp_bi.dispDeviceRowBytes, disp_bi.dispDeviceRowBytes);
657 #endif /* CONFIG_BOOTX_TEXT */
659 static unsigned short fcstab[256] = {
660 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
661 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
662 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
663 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
664 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
665 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
666 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
667 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
668 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
669 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
670 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
671 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
672 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
673 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
674 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
675 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
676 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
677 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
678 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
679 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
680 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
681 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
682 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
683 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
684 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
685 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
686 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
687 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
688 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
689 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
690 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
691 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
694 #define FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
705 if (!scanhex(&ncsum))
708 for (i = 0; i < ncsum; ++i) {
709 if (mread(adrs+i, &v, 1) == 0) {
710 printf("csum stopped at %x\n", adrs+i);
728 #if !defined(CONFIG_8xx)
745 dabr.enabled = scanhex(&dabr.address);
746 scanhex(&dabr.count);
748 dabr.address = (dabr.address & ~7) | mode;
758 iabr.enabled = scanhex(&iabr.address);
760 iabr.address |= mode;
761 scanhex(&iabr.count);
766 /* clear all breakpoints */
767 for (i = 0; i < NBPTS; ++i)
771 printf("All breakpoints cleared\n");
773 bp = at_breakpoint(a);
775 printf("No breakpoint at %x\n", a);
784 /* print all breakpoints */
785 printf("type address count\n");
787 printf("data %.8x %8x [", dabr.address & ~7,
789 if (dabr.address & 1)
791 if (dabr.address & 2)
793 if (!(dabr.address & 4))
798 printf("inst %.8x %8x\n", iabr.address & ~3,
800 for (bp = bpts; bp < &bpts[NBPTS]; ++bp)
802 printf("trap %.8x %8x\n", bp->address,
806 bp = at_breakpoint(a);
808 for (bp = bpts; bp < &bpts[NBPTS]; ++bp)
811 if (bp >= &bpts[NBPTS]) {
812 printf("Sorry, no free breakpoints\n");
825 backtrace(struct pt_regs *excp)
830 extern char ret_from_except, ret_from_except_full, ret_from_syscall;
832 printf("backtrace:\n");
840 for (; sp != 0; sp = stack[0]) {
841 if (mread(sp, stack, sizeof(stack)) != sizeof(stack))
843 printf("[%.8lx] ", stack);
844 xmon_print_symbol(stack[1], " ", "\n");
845 if (stack[1] == (unsigned) &ret_from_except
846 || stack[1] == (unsigned) &ret_from_except_full
847 || stack[1] == (unsigned) &ret_from_syscall) {
848 if (mread(sp+16, ®s, sizeof(regs)) != sizeof(regs))
850 printf("exception:%x [%x] %x\n", regs.trap, sp+16,
853 if (mread(sp, stack, sizeof(stack)) != sizeof(stack))
864 asm("mr %0,1" : "=r" (x) :);
869 excprint(struct pt_regs *fp)
874 printf("cpu %d: ", smp_processor_id());
875 #endif /* CONFIG_SMP */
876 printf("vector: %x at pc=", fp->trap);
877 xmon_print_symbol(fp->nip, ": ", ", lr=");
878 xmon_print_symbol(fp->link, ": ", "\n");
879 printf("msr = %x, sp = %x [%x]\n", fp->msr, fp->gpr[1], fp);
881 if (trap == 0x300 || trap == 0x600)
882 printf("dar = %x, dsisr = %x\n", fp->dar, fp->dsisr);
884 printf("current = %x, pid = %d, comm = %s\n",
885 current, current->pid, current->comm);
889 prregs(struct pt_regs *fp)
895 fp = (struct pt_regs *) base;
896 for (n = 0; n < 32; ++n) {
897 printf("R%.2d = %.8x%s", n, fp->gpr[n],
898 (n & 3) == 3? "\n": " ");
899 if (n == 12 && !FULL_REGS(fp)) {
904 printf("pc = %.8x msr = %.8x lr = %.8x cr = %.8x\n",
905 fp->nip, fp->msr, fp->link, fp->ccr);
906 printf("ctr = %.8x xer = %.8x trap = %4x\n",
907 fp->ctr, fp->xer, fp->trap);
924 nflush = (nflush + 31) / 32;
926 for (; nflush > 0; --nflush, adrs += 0x20)
927 cflush((void *) adrs);
929 for (; nflush > 0; --nflush, adrs += 0x20)
930 cinval((void *) adrs);
937 unsigned int instrs[2];
940 instrs[0] = 0x7c6002a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
941 instrs[1] = 0x4e800020;
943 store_inst(instrs+1);
944 code = (int (*)(void)) instrs;
949 write_spr(int n, unsigned int val)
951 unsigned int instrs[2];
952 int (*code)(unsigned int);
954 instrs[0] = 0x7c6003a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
955 instrs[1] = 0x4e800020;
957 store_inst(instrs+1);
958 code = (int (*)(unsigned int)) instrs;
962 static unsigned int regno;
963 extern char exc_prolog;
974 printf("msr = %x, pvr = %x\n", get_msr(), get_pvr());
975 printf("sprg0-3 = %x %x %x %x\n", get_sprg0(), get_sprg1(),
976 get_sprg2(), get_sprg3());
977 printf("srr0 = %x, srr1 = %x\n", get_srr0(), get_srr1());
978 #ifdef CONFIG_PPC_STD_MMU
980 for (i = 0; i < 16; ++i)
981 printf(" %x", get_sr(i));
984 asm("mr %0,1" : "=r" (i) :);
985 printf("sp = %x ", i);
986 asm("mr %0,2" : "=r" (i) :);
987 printf("toc = %x\n", i);
994 val = read_spr(regno);
996 write_spr(regno, val);
999 printf("spr %x = %x\n", regno, read_spr(regno));
1002 val = get_sr(regno);
1015 #ifndef CONFIG_PPC_STD_MMU
1017 dump_hash_table(void)
1019 printf("This CPU doesn't have a hash table.\n");
1023 #ifndef CONFIG_PPC64BRIDGE
1025 dump_hash_table_seg(unsigned seg, unsigned start, unsigned end)
1028 extern unsigned long Hash_size;
1029 unsigned *htab = Hash;
1030 unsigned hsize = Hash_size;
1031 unsigned v, hmask, va, last_va = 0;
1032 int found, last_found, i;
1033 unsigned *hg, w1, last_w2 = 0, last_va0 = 0;
1036 hmask = hsize / 64 - 1;
1038 start = (start >> 12) & 0xffff;
1039 end = (end >> 12) & 0xffff;
1040 for (v = start; v < end; ++v) {
1042 hg = htab + (((v ^ seg) & hmask) * 16);
1043 w1 = 0x80000000 | (seg << 7) | (v >> 10);
1044 for (i = 0; i < 8; ++i, hg += 2) {
1052 hg = htab + ((~(v ^ seg) & hmask) * 16);
1053 for (i = 0; i < 8; ++i, hg += 2) {
1060 if (!(last_found && found && (hg[1] & ~0x180) == last_w2 + 4096)) {
1062 if (last_va != last_va0)
1063 printf(" ... %x", last_va);
1067 printf("%x to %x", va, hg[1]);
1073 last_w2 = hg[1] & ~0x180;
1079 printf(" ... %x\n", last_va);
1082 #else /* CONFIG_PPC64BRIDGE */
1084 dump_hash_table_seg(unsigned seg, unsigned start, unsigned end)
1087 extern unsigned long Hash_size;
1088 unsigned *htab = Hash;
1089 unsigned hsize = Hash_size;
1090 unsigned v, hmask, va, last_va;
1091 int found, last_found, i;
1092 unsigned *hg, w1, last_w2, last_va0;
1095 hmask = hsize / 128 - 1;
1097 start = (start >> 12) & 0xffff;
1098 end = (end >> 12) & 0xffff;
1099 for (v = start; v < end; ++v) {
1101 hg = htab + (((v ^ seg) & hmask) * 32);
1102 w1 = 1 | (seg << 12) | ((v & 0xf800) >> 4);
1103 for (i = 0; i < 8; ++i, hg += 4) {
1111 hg = htab + ((~(v ^ seg) & hmask) * 32);
1112 for (i = 0; i < 8; ++i, hg += 4) {
1119 if (!(last_found && found && (hg[3] & ~0x180) == last_w2 + 4096)) {
1121 if (last_va != last_va0)
1122 printf(" ... %x", last_va);
1126 printf("%x to %x", va, hg[3]);
1132 last_w2 = hg[3] & ~0x180;
1138 printf(" ... %x\n", last_va);
1140 #endif /* CONFIG_PPC64BRIDGE */
1142 static unsigned hash_ctx;
1143 static unsigned hash_start;
1144 static unsigned hash_end;
1147 dump_hash_table(void)
1150 unsigned seg_start, seg_end;
1154 hash_end = 0xfffff000;
1156 scanhex(&hash_start);
1158 printf("Mappings for context %x\n", hash_ctx);
1159 seg_start = hash_start;
1160 for (seg = hash_start >> 28; seg <= hash_end >> 28; ++seg) {
1161 seg_end = (seg << 28) | 0x0ffff000;
1162 if (seg_end > hash_end)
1164 dump_hash_table_seg((hash_ctx << 4) + (seg * 0x111),
1165 seg_start, seg_end);
1166 seg_start = seg_end + 0x1000;
1169 #endif /* CONFIG_PPC_STD_MMU */
1172 * Stuff for reading and writing memory safely
1176 mread(unsigned adrs, void *buf, int size)
1182 if( setjmp(bus_error_jmp) == 0 ){
1183 debugger_fault_handler = handle_fault;
1188 case 2: *(short *)q = *(short *)p; break;
1189 case 4: *(int *)q = *(int *)p; break;
1191 for( ; n < size; ++n ) {
1197 /* wait a little while to see if we get a machine check */
1201 debugger_fault_handler = NULL;
1206 mwrite(unsigned adrs, void *buf, int size)
1212 if( setjmp(bus_error_jmp) == 0 ){
1213 debugger_fault_handler = handle_fault;
1218 case 2: *(short *)p = *(short *)q; break;
1219 case 4: *(int *)p = *(int *)q; break;
1221 for( ; n < size; ++n ) {
1229 printf("*** Error writing address %x\n", adrs + n);
1231 debugger_fault_handler = NULL;
1235 static int fault_type;
1236 static int fault_except;
1237 static char *fault_chars[] = { "--", "**", "##" };
1240 handle_fault(struct pt_regs *regs)
1242 fault_except = TRAP(regs);
1243 fault_type = TRAP(regs) == 0x200? 0: TRAP(regs) == 0x300? 1: 2;
1244 longjmp(bus_error_jmp, 1);
1247 #define SWAP(a, b, t) ((t) = (a), (a) = (b), (b) = (t))
1250 byterev(unsigned char *val, int size)
1256 SWAP(val[0], val[1], t);
1259 SWAP(val[0], val[3], t);
1260 SWAP(val[1], val[2], t);
1271 int cmd, inc, i, nslash;
1273 unsigned char val[4];
1277 while ((cmd = skipbl()) != '\n') {
1279 case 'b': size = 1; break;
1280 case 'w': size = 2; break;
1281 case 'l': size = 4; break;
1282 case 'r': brev = !brev; break;
1283 case 'n': mnoread = 1; break;
1284 case '.': mnoread = 0; break;
1293 n = mread(adrs, val, size);
1294 printf("%.8x%c", adrs, brev? 'r': ' ');
1299 for (i = 0; i < n; ++i)
1300 printf("%.2x", val[i]);
1301 for (; i < size; ++i)
1302 printf("%s", fault_chars[fault_type]);
1309 for (i = 0; i < size; ++i)
1310 val[i] = n >> (i * 8);
1313 mwrite(adrs, val, size);
1326 else if( n == '\'' )
1328 for (i = 0; i < size; ++i)
1329 val[i] = n >> (i * 8);
1332 mwrite(adrs, val, size);
1366 adrs -= 1 << nslash;
1370 adrs += 1 << nslash;
1374 adrs += 1 << -nslash;
1378 adrs -= 1 << -nslash;
1412 case 'n': c = '\n'; break;
1413 case 'r': c = '\r'; break;
1414 case 'b': c = '\b'; break;
1415 case 't': c = '\t'; break;
1426 if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')
1435 adrs += ppc_inst_dump(adrs, nidump);
1441 prdump(adrs, ndump);
1448 prdump(unsigned adrs, int ndump)
1450 register int n, m, c, r, nr;
1451 unsigned char temp[16];
1453 for( n = ndump; n > 0; ){
1454 printf("%.8x", adrs);
1457 nr = mread(adrs, temp, r);
1459 for( m = 0; m < r; ++m ){
1460 putchar((m & 3) == 0 && m > 0? '.': ' ');
1462 printf("%.2x", temp[m]);
1464 printf("%s", fault_chars[fault_type]);
1469 for( m = 0; m < r; ++m ){
1472 putchar(' ' <= c && c <= '~'? c: '.');
1486 ppc_inst_dump(unsigned adr, int count)
1490 unsigned long inst, last_inst = 0;
1491 unsigned char val[4];
1494 for (first_adr = adr; count > 0; --count, adr += 4){
1495 nr = mread(adr, val, 4);
1497 const char *x = fault_chars[fault_type];
1498 printf("%.8x %s%s%s%s\n", adr, x, x, x, x);
1501 inst = GETWORD(val);
1502 if (adr > first_adr && inst == last_inst) {
1511 printf("%.8x ", adr);
1512 printf("%.8x\t", inst);
1513 print_insn_big_powerpc(stdout, inst, adr); /* always returns 4 */
1516 return adr - first_adr;
1520 print_address(unsigned addr)
1522 printf("0x%x", addr);
1526 * Memory operations - move, set, print differences
1528 static unsigned mdest; /* destination address */
1529 static unsigned msrc; /* source address */
1530 static unsigned mval; /* byte value to set memory to */
1531 static unsigned mcount; /* # bytes to affect */
1532 static unsigned mdiffs; /* max # differences to print */
1538 if( termch != '\n' )
1540 scanhex(cmd == 's'? &mval: &msrc);
1541 if( termch != '\n' )
1546 memmove((void *)mdest, (void *)msrc, mcount);
1549 memset((void *)mdest, mval, mcount);
1552 if( termch != '\n' )
1555 memdiffs((unsigned char *)mdest, (unsigned char *)msrc, mcount, mdiffs);
1561 memdiffs(unsigned char *p1, unsigned char *p2, unsigned nb, unsigned maxpr)
1566 for( n = nb; n > 0; --n )
1567 if( *p1++ != *p2++ )
1568 if( ++prt <= maxpr )
1569 printf("%.8x %.2x # %.8x %.2x\n", (unsigned)p1 - 1,
1570 p1[-1], (unsigned)p2 - 1, p2[-1]);
1572 printf("Total of %d differences\n", prt);
1575 static unsigned mend;
1576 static unsigned mask;
1582 unsigned char val[4];
1586 if (termch != '\n') {
1589 if (termch != '\n') {
1593 if (termch != '\n') termch = 0;
1598 for (a = mdest; a < mend; a += 4) {
1599 if (mread(a, val, 4) == 4
1600 && ((GETWORD(val) ^ mval) & mask) == 0) {
1601 printf("%.8x: %.8x\n", a, GETWORD(val));
1608 static unsigned mskip = 0x1000;
1609 static unsigned mlim = 0xffffffff;
1619 if (termch != '\n') termch = 0;
1621 if (termch != '\n') termch = 0;
1624 for (a = mdest; a < mlim; a += mskip) {
1625 ok = mread(a, &v, 1);
1627 printf("%.8x .. ", a);
1629 } else if (!ok && ook)
1630 printf("%.8x\n", a - mskip);
1636 printf("%.8x\n", a - mskip);
1641 unsigned int args[8];
1644 typedef unsigned int (*callfunc_t)(unsigned int, unsigned int,
1645 unsigned int, unsigned int, unsigned int,
1646 unsigned int, unsigned int, unsigned int);
1652 for (i = 0; i < 8; ++i)
1654 for (i = 0; i < 8; ++i) {
1655 if (!scanhex(&args[i]) || termch == '\n')
1659 func = (callfunc_t) adrs;
1661 if (setjmp(bus_error_jmp) == 0) {
1662 debugger_fault_handler = handle_fault;
1664 ret = func(args[0], args[1], args[2], args[3],
1665 args[4], args[5], args[6], args[7]);
1667 printf("return value is %x\n", ret);
1669 printf("*** %x exception occurred\n", fault_except);
1671 debugger_fault_handler = NULL;
1674 /* Input scanning routines */
1685 while( c == ' ' || c == '\t' )
1691 static char *regnames[N_PTREGS] = {
1692 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
1693 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
1694 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
1695 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
1696 "pc", "msr", "or3", "ctr", "lr", "xer", "ccr", "mq",
1697 "trap", "dar", "dsisr", "res"
1701 scanhex(unsigned *vp)
1708 /* parse register name */
1712 for (i = 0; i < sizeof(regname) - 1; ++i) {
1721 for (i = 0; i < N_PTREGS; ++i) {
1722 if (strcmp(regnames[i], regname) == 0) {
1723 unsigned *rp = (unsigned *)
1724 xmon_regs[smp_processor_id()];
1726 printf("regs not available\n");
1733 printf("invalid register name '%%%s'\n", regname);
1735 } else if (c == '$') {
1736 static char symname[128];
1738 for (i=0; i<63; i++) {
1748 if (setjmp(bus_error_jmp) == 0) {
1749 debugger_fault_handler = handle_fault;
1751 *vp = kallsyms_lookup_name(symname);
1754 debugger_fault_handler = NULL;
1756 printf("unknown symbol\n");
1772 } while( d != EOF );
1791 if( '0' <= c && c <= '9' )
1793 if( 'A' <= c && c <= 'F' )
1794 return c - ('A' - 10);
1795 if( 'a' <= c && c <= 'f' )
1796 return c - ('a' - 10);
1801 getstring(char *s, int size)
1812 } while( c != ' ' && c != '\t' && c != '\n' );
1817 static char line[256];
1818 static char *lineptr;
1829 if (lineptr == NULL || *lineptr == 0) {
1830 if (fgets(line, sizeof(line), stdin) == NULL) {
1840 take_input(char *str)
1848 int type = inchar();
1850 static char tmp[128];
1855 xmon_print_symbol(addr, ": ", "\n");
1860 if (setjmp(bus_error_jmp) == 0) {
1861 debugger_fault_handler = handle_fault;
1863 addr = kallsyms_lookup_name(tmp);
1865 printf("%s: %lx\n", tmp, addr);
1867 printf("Symbol '%s' not found.\n", tmp);
1870 debugger_fault_handler = NULL;