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\
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);
224 xmon(struct pt_regs *excp)
229 get_tb(stop_tb[smp_processor_id()]);
231 asm volatile ("stw 0,0(%0)\n\
234 stmw 2,8(%0)" : : "b" (®s));
235 regs.nip = regs.link = ((unsigned long *)regs.gpr[1])[1];
236 regs.msr = get_msr();
237 regs.ctr = get_ctr();
238 regs.xer = get_xer();
245 set_msr(msr & ~0x8000); /* disable interrupts */
246 xmon_regs[smp_processor_id()] = excp;
250 if (test_and_set_bit(smp_processor_id(), &cpus_in_xmon))
253 while (test_and_set_bit(0, &got_xmon)) {
254 if (take_xmon == smp_processor_id()) {
260 * XXX: breakpoints are removed while any cpu is in xmon
262 #endif /* CONFIG_SMP */
264 #ifdef CONFIG_PMAC_BACKLIGHT
265 if( setjmp(bus_error_jmp) == 0 ) {
266 debugger_fault_handler = handle_fault;
268 set_backlight_enable(1);
269 set_backlight_level(BACKLIGHT_MAX);
272 debugger_fault_handler = NULL;
273 #endif /* CONFIG_PMAC_BACKLIGHT */
276 xmon_trace[smp_processor_id()] = SSTEP;
278 } else if (at_breakpoint(excp->nip)) {
279 xmon_trace[smp_processor_id()] = BRSTEP;
282 xmon_trace[smp_processor_id()] = 0;
286 xmon_regs[smp_processor_id()] = NULL;
288 clear_bit(0, &got_xmon);
289 clear_bit(smp_processor_id(), &cpus_in_xmon);
290 #endif /* CONFIG_SMP */
291 set_msr(msr); /* restore interrupt enable */
292 get_tb(start_tb[smp_processor_id()]);
296 xmon_irq(int irq, void *d, struct pt_regs *regs)
299 local_irq_save(flags);
300 printf("Keyboard interrupt\n");
302 local_irq_restore(flags);
307 xmon_bpt(struct pt_regs *regs)
311 bp = at_breakpoint(regs->nip);
318 xmon_trace[smp_processor_id()] = BRSTEP;
327 xmon_sstep(struct pt_regs *regs)
329 if (!xmon_trace[smp_processor_id()])
331 if (xmon_trace[smp_processor_id()] == BRSTEP) {
332 xmon_trace[smp_processor_id()] = 0;
341 xmon_dabr_match(struct pt_regs *regs)
343 if (dabr.enabled && dabr.count) {
347 xmon_trace[smp_processor_id()] = BRSTEP;
350 dabr.instr = regs->nip;
357 xmon_iabr_match(struct pt_regs *regs)
359 if (iabr.enabled && iabr.count) {
363 xmon_trace[smp_processor_id()] = BRSTEP;
372 at_breakpoint(unsigned pc)
377 if (dabr.enabled && pc == dabr.instr)
379 if (iabr.enabled && pc == iabr.address)
382 for (i = 0; i < NBPTS; ++i, ++bp)
383 if (bp->enabled && pc == bp->address)
395 for (i = 0; i < NBPTS; ++i, ++bp) {
398 if (mread(bp->address, &bp->instr, 4) != 4
399 || mwrite(bp->address, &bpinstr, 4) != 4) {
400 printf("Couldn't insert breakpoint at %x, disabling\n",
404 store_inst((void *) bp->address);
406 #if !defined(CONFIG_8xx)
408 set_dabr(dabr.address);
410 set_iabr(iabr.address);
421 #if !defined(CONFIG_8xx)
426 for (i = 0; i < NBPTS; ++i, ++bp) {
429 if (mread(bp->address, &instr, 4) == 4
431 && mwrite(bp->address, &bp->instr, 4) != 4)
432 printf("Couldn't remove breakpoint at %x\n",
434 store_inst((void *) bp->address);
438 static char *last_cmd;
440 /* Command interpreting routine */
442 cmds(struct pt_regs *excp)
449 printf("%d:", smp_processor_id());
450 #endif /* CONFIG_SMP */
457 if (last_cmd == NULL)
459 take_input(last_cmd);
491 prregs(excp); /* print regs */
495 printf("No exception information\n");
519 printf("Unrecognized command: ");
520 if( ' ' < cmd && cmd <= '~' )
523 printf("\\x%x", cmd);
524 printf(" (type ? for help)\n");
536 #endif /* CONFIG_SMP */
537 #ifdef CONFIG_BOOTX_TEXT
555 extern unsigned tb_to_us;
557 #define mulhwu(x,y) \
558 ({unsigned z; asm ("mulhwu %0,%1,%2" : "=r" (z) : "r" (x), "r" (y)); z;})
560 static void printtime(void)
564 delta = stop_tb[smp_processor_id()][1]
565 - start_tb[smp_processor_id()][1];
566 delta = mulhwu(tb_to_us, delta);
567 printf("%u.%06u seconds\n", delta / 1000000, delta % 1000000);
570 static void bootcmds(void)
576 ppc_md.restart(NULL);
584 static void cpu_cmd(void)
592 /* interrupt other cpu(s) */
593 cpu = MSG_ALL_BUT_SELF;
595 smp_send_xmon_break(cpu);
599 if (!scanhex(&cpu)) {
600 /* print cpus waiting or in xmon */
601 printf("cpus stopped:");
602 for (cpu = 0; cpu < NR_CPUS; ++cpu) {
603 if (test_bit(cpu, &cpus_in_xmon)) {
605 if (cpu == smp_processor_id())
612 /* try to switch to cpu specified */
615 while (take_xmon >= 0) {
616 if (--timeout == 0) {
617 /* yes there's a race here */
619 printf("cpu %u didn't take control\n", cpu);
623 /* now have to wait to be given control back */
624 while (test_and_set_bit(0, &got_xmon)) {
625 if (take_xmon == smp_processor_id()) {
631 #endif /* CONFIG_SMP */
633 #ifdef CONFIG_BOOTX_TEXT
634 extern boot_infos_t disp_bi;
636 static void vidcmds(void)
640 extern int boot_text_mapped;
642 if (!boot_text_mapped)
644 if (c != '\n' && scanhex(&val)) {
647 w = disp_bi.dispDeviceRowBytes
648 / (disp_bi.dispDeviceDepth >> 3);
649 disp_bi.dispDeviceDepth = val;
650 disp_bi.dispDeviceRowBytes = w * (val >> 3);
653 disp_bi.dispDeviceRowBytes = val;
656 disp_bi.dispDeviceRect[2] = val;
659 disp_bi.dispDeviceRect[3] = val;
663 printf("W = %d (0x%x) H = %d (0x%x) D = %d (0x%x) P = %d (0x%x)\n",
664 disp_bi.dispDeviceRect[2], disp_bi.dispDeviceRect[2],
665 disp_bi.dispDeviceRect[3], disp_bi.dispDeviceRect[3],
666 disp_bi.dispDeviceDepth, disp_bi.dispDeviceDepth,
667 disp_bi.dispDeviceRowBytes, disp_bi.dispDeviceRowBytes);
669 #endif /* CONFIG_BOOTX_TEXT */
671 static unsigned short fcstab[256] = {
672 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
673 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
674 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
675 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
676 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
677 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
678 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
679 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
680 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
681 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
682 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
683 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
684 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
685 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
686 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
687 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
688 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
689 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
690 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
691 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
692 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
693 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
694 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
695 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
696 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
697 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
698 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
699 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
700 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
701 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
702 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
703 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
706 #define FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
717 if (!scanhex(&ncsum))
720 for (i = 0; i < ncsum; ++i) {
721 if (mread(adrs+i, &v, 1) == 0) {
722 printf("csum stopped at %x\n", adrs+i);
740 #if !defined(CONFIG_8xx)
757 dabr.enabled = scanhex(&dabr.address);
758 scanhex(&dabr.count);
760 dabr.address = (dabr.address & ~7) | mode;
770 iabr.enabled = scanhex(&iabr.address);
772 iabr.address |= mode;
773 scanhex(&iabr.count);
778 /* clear all breakpoints */
779 for (i = 0; i < NBPTS; ++i)
783 printf("All breakpoints cleared\n");
785 bp = at_breakpoint(a);
787 printf("No breakpoint at %x\n", a);
796 /* print all breakpoints */
797 printf("type address count\n");
799 printf("data %.8x %8x [", dabr.address & ~7,
801 if (dabr.address & 1)
803 if (dabr.address & 2)
805 if (!(dabr.address & 4))
810 printf("inst %.8x %8x\n", iabr.address & ~3,
812 for (bp = bpts; bp < &bpts[NBPTS]; ++bp)
814 printf("trap %.8x %8x\n", bp->address,
818 bp = at_breakpoint(a);
820 for (bp = bpts; bp < &bpts[NBPTS]; ++bp)
823 if (bp >= &bpts[NBPTS]) {
824 printf("Sorry, no free breakpoints\n");
837 backtrace(struct pt_regs *excp)
842 extern char ret_from_except, ret_from_except_full, ret_from_syscall;
844 printf("backtrace:\n");
852 for (; sp != 0; sp = stack[0]) {
853 if (mread(sp, stack, sizeof(stack)) != sizeof(stack))
855 printf("[%.8lx] ", stack);
856 xmon_print_symbol(stack[1], " ", "\n");
857 if (stack[1] == (unsigned) &ret_from_except
858 || stack[1] == (unsigned) &ret_from_except_full
859 || stack[1] == (unsigned) &ret_from_syscall) {
860 if (mread(sp+16, ®s, sizeof(regs)) != sizeof(regs))
862 printf("exception:%x [%x] %x\n", regs.trap, sp+16,
865 if (mread(sp, stack, sizeof(stack)) != sizeof(stack))
876 asm("mr %0,1" : "=r" (x) :);
881 excprint(struct pt_regs *fp)
886 printf("cpu %d: ", smp_processor_id());
887 #endif /* CONFIG_SMP */
888 printf("vector: %x at pc=", fp->trap);
889 xmon_print_symbol(fp->nip, ": ", ", lr=");
890 xmon_print_symbol(fp->link, ": ", "\n");
891 printf("msr = %x, sp = %x [%x]\n", fp->msr, fp->gpr[1], fp);
893 if (trap == 0x300 || trap == 0x600)
894 printf("dar = %x, dsisr = %x\n", fp->dar, fp->dsisr);
896 printf("current = %x, pid = %d, comm = %s\n",
897 current, current->pid, current->comm);
901 prregs(struct pt_regs *fp)
907 fp = (struct pt_regs *) base;
908 for (n = 0; n < 32; ++n) {
909 printf("R%.2d = %.8x%s", n, fp->gpr[n],
910 (n & 3) == 3? "\n": " ");
911 if (n == 12 && !FULL_REGS(fp)) {
916 printf("pc = %.8x msr = %.8x lr = %.8x cr = %.8x\n",
917 fp->nip, fp->msr, fp->link, fp->ccr);
918 printf("ctr = %.8x xer = %.8x trap = %4x\n",
919 fp->ctr, fp->xer, fp->trap);
936 nflush = (nflush + 31) / 32;
938 for (; nflush > 0; --nflush, adrs += 0x20)
939 cflush((void *) adrs);
941 for (; nflush > 0; --nflush, adrs += 0x20)
942 cinval((void *) adrs);
949 unsigned int instrs[2];
952 instrs[0] = 0x7c6002a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
953 instrs[1] = 0x4e800020;
955 store_inst(instrs+1);
956 code = (int (*)(void)) instrs;
961 write_spr(int n, unsigned int val)
963 unsigned int instrs[2];
964 int (*code)(unsigned int);
966 instrs[0] = 0x7c6003a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
967 instrs[1] = 0x4e800020;
969 store_inst(instrs+1);
970 code = (int (*)(unsigned int)) instrs;
974 static unsigned int regno;
975 extern char exc_prolog;
986 printf("msr = %x, pvr = %x\n", get_msr(), get_pvr());
987 printf("sprg0-3 = %x %x %x %x\n", get_sprg0(), get_sprg1(),
988 get_sprg2(), get_sprg3());
989 printf("srr0 = %x, srr1 = %x\n", get_srr0(), get_srr1());
990 #ifdef CONFIG_PPC_STD_MMU
992 for (i = 0; i < 16; ++i)
993 printf(" %x", get_sr(i));
996 asm("mr %0,1" : "=r" (i) :);
997 printf("sp = %x ", i);
998 asm("mr %0,2" : "=r" (i) :);
999 printf("toc = %x\n", i);
1006 val = read_spr(regno);
1008 write_spr(regno, val);
1011 printf("spr %x = %x\n", regno, read_spr(regno));
1014 val = get_sr(regno);
1027 #ifndef CONFIG_PPC_STD_MMU
1029 dump_hash_table(void)
1031 printf("This CPU doesn't have a hash table.\n");
1035 #ifndef CONFIG_PPC64BRIDGE
1037 dump_hash_table_seg(unsigned seg, unsigned start, unsigned end)
1040 extern unsigned long Hash_size;
1041 unsigned *htab = Hash;
1042 unsigned hsize = Hash_size;
1043 unsigned v, hmask, va, last_va = 0;
1044 int found, last_found, i;
1045 unsigned *hg, w1, last_w2 = 0, last_va0 = 0;
1048 hmask = hsize / 64 - 1;
1050 start = (start >> 12) & 0xffff;
1051 end = (end >> 12) & 0xffff;
1052 for (v = start; v < end; ++v) {
1054 hg = htab + (((v ^ seg) & hmask) * 16);
1055 w1 = 0x80000000 | (seg << 7) | (v >> 10);
1056 for (i = 0; i < 8; ++i, hg += 2) {
1064 hg = htab + ((~(v ^ seg) & hmask) * 16);
1065 for (i = 0; i < 8; ++i, hg += 2) {
1072 if (!(last_found && found && (hg[1] & ~0x180) == last_w2 + 4096)) {
1074 if (last_va != last_va0)
1075 printf(" ... %x", last_va);
1079 printf("%x to %x", va, hg[1]);
1085 last_w2 = hg[1] & ~0x180;
1091 printf(" ... %x\n", last_va);
1094 #else /* CONFIG_PPC64BRIDGE */
1096 dump_hash_table_seg(unsigned seg, unsigned start, unsigned end)
1099 extern unsigned long Hash_size;
1100 unsigned *htab = Hash;
1101 unsigned hsize = Hash_size;
1102 unsigned v, hmask, va, last_va;
1103 int found, last_found, i;
1104 unsigned *hg, w1, last_w2, last_va0;
1107 hmask = hsize / 128 - 1;
1109 start = (start >> 12) & 0xffff;
1110 end = (end >> 12) & 0xffff;
1111 for (v = start; v < end; ++v) {
1113 hg = htab + (((v ^ seg) & hmask) * 32);
1114 w1 = 1 | (seg << 12) | ((v & 0xf800) >> 4);
1115 for (i = 0; i < 8; ++i, hg += 4) {
1123 hg = htab + ((~(v ^ seg) & hmask) * 32);
1124 for (i = 0; i < 8; ++i, hg += 4) {
1131 if (!(last_found && found && (hg[3] & ~0x180) == last_w2 + 4096)) {
1133 if (last_va != last_va0)
1134 printf(" ... %x", last_va);
1138 printf("%x to %x", va, hg[3]);
1144 last_w2 = hg[3] & ~0x180;
1150 printf(" ... %x\n", last_va);
1152 #endif /* CONFIG_PPC64BRIDGE */
1154 static unsigned hash_ctx;
1155 static unsigned hash_start;
1156 static unsigned hash_end;
1159 dump_hash_table(void)
1162 unsigned seg_start, seg_end;
1166 hash_end = 0xfffff000;
1168 scanhex(&hash_start);
1170 printf("Mappings for context %x\n", hash_ctx);
1171 seg_start = hash_start;
1172 for (seg = hash_start >> 28; seg <= hash_end >> 28; ++seg) {
1173 seg_end = (seg << 28) | 0x0ffff000;
1174 if (seg_end > hash_end)
1176 dump_hash_table_seg((hash_ctx << 4) + (seg * 0x111),
1177 seg_start, seg_end);
1178 seg_start = seg_end + 0x1000;
1181 #endif /* CONFIG_PPC_STD_MMU */
1184 * Stuff for reading and writing memory safely
1188 mread(unsigned adrs, void *buf, int size)
1194 if( setjmp(bus_error_jmp) == 0 ){
1195 debugger_fault_handler = handle_fault;
1200 case 2: *(short *)q = *(short *)p; break;
1201 case 4: *(int *)q = *(int *)p; break;
1203 for( ; n < size; ++n ) {
1209 /* wait a little while to see if we get a machine check */
1213 debugger_fault_handler = NULL;
1218 mwrite(unsigned adrs, void *buf, int size)
1224 if( setjmp(bus_error_jmp) == 0 ){
1225 debugger_fault_handler = handle_fault;
1230 case 2: *(short *)p = *(short *)q; break;
1231 case 4: *(int *)p = *(int *)q; break;
1233 for( ; n < size; ++n ) {
1241 printf("*** Error writing address %x\n", adrs + n);
1243 debugger_fault_handler = NULL;
1247 static int fault_type;
1248 static int fault_except;
1249 static char *fault_chars[] = { "--", "**", "##" };
1252 handle_fault(struct pt_regs *regs)
1254 fault_except = TRAP(regs);
1255 fault_type = TRAP(regs) == 0x200? 0: TRAP(regs) == 0x300? 1: 2;
1256 longjmp(bus_error_jmp, 1);
1259 #define SWAP(a, b, t) ((t) = (a), (a) = (b), (b) = (t))
1262 byterev(unsigned char *val, int size)
1268 SWAP(val[0], val[1], t);
1271 SWAP(val[0], val[3], t);
1272 SWAP(val[1], val[2], t);
1283 int cmd, inc, i, nslash;
1285 unsigned char val[4];
1289 while ((cmd = skipbl()) != '\n') {
1291 case 'b': size = 1; break;
1292 case 'w': size = 2; break;
1293 case 'l': size = 4; break;
1294 case 'r': brev = !brev; break;
1295 case 'n': mnoread = 1; break;
1296 case '.': mnoread = 0; break;
1305 n = mread(adrs, val, size);
1306 printf("%.8x%c", adrs, brev? 'r': ' ');
1311 for (i = 0; i < n; ++i)
1312 printf("%.2x", val[i]);
1313 for (; i < size; ++i)
1314 printf("%s", fault_chars[fault_type]);
1321 for (i = 0; i < size; ++i)
1322 val[i] = n >> (i * 8);
1325 mwrite(adrs, val, size);
1338 else if( n == '\'' )
1340 for (i = 0; i < size; ++i)
1341 val[i] = n >> (i * 8);
1344 mwrite(adrs, val, size);
1378 adrs -= 1 << nslash;
1382 adrs += 1 << nslash;
1386 adrs += 1 << -nslash;
1390 adrs -= 1 << -nslash;
1424 case 'n': c = '\n'; break;
1425 case 'r': c = '\r'; break;
1426 case 'b': c = '\b'; break;
1427 case 't': c = '\t'; break;
1438 if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')
1447 adrs += ppc_inst_dump(adrs, nidump);
1453 prdump(adrs, ndump);
1460 prdump(unsigned adrs, int ndump)
1462 register int n, m, c, r, nr;
1463 unsigned char temp[16];
1465 for( n = ndump; n > 0; ){
1466 printf("%.8x", adrs);
1469 nr = mread(adrs, temp, r);
1471 for( m = 0; m < r; ++m ){
1472 putchar((m & 3) == 0 && m > 0? '.': ' ');
1474 printf("%.2x", temp[m]);
1476 printf("%s", fault_chars[fault_type]);
1481 for( m = 0; m < r; ++m ){
1484 putchar(' ' <= c && c <= '~'? c: '.');
1498 ppc_inst_dump(unsigned adr, int count)
1502 unsigned long inst, last_inst = 0;
1503 unsigned char val[4];
1506 for (first_adr = adr; count > 0; --count, adr += 4){
1507 nr = mread(adr, val, 4);
1509 const char *x = fault_chars[fault_type];
1510 printf("%.8x %s%s%s%s\n", adr, x, x, x, x);
1513 inst = GETWORD(val);
1514 if (adr > first_adr && inst == last_inst) {
1523 printf("%.8x ", adr);
1524 printf("%.8x\t", inst);
1525 print_insn_big_powerpc(stdout, inst, adr); /* always returns 4 */
1528 return adr - first_adr;
1532 print_address(unsigned addr)
1534 printf("0x%x", addr);
1538 * Memory operations - move, set, print differences
1540 static unsigned mdest; /* destination address */
1541 static unsigned msrc; /* source address */
1542 static unsigned mval; /* byte value to set memory to */
1543 static unsigned mcount; /* # bytes to affect */
1544 static unsigned mdiffs; /* max # differences to print */
1550 if( termch != '\n' )
1552 scanhex(cmd == 's'? &mval: &msrc);
1553 if( termch != '\n' )
1558 memmove((void *)mdest, (void *)msrc, mcount);
1561 memset((void *)mdest, mval, mcount);
1564 if( termch != '\n' )
1567 memdiffs((unsigned char *)mdest, (unsigned char *)msrc, mcount, mdiffs);
1573 memdiffs(unsigned char *p1, unsigned char *p2, unsigned nb, unsigned maxpr)
1578 for( n = nb; n > 0; --n )
1579 if( *p1++ != *p2++ )
1580 if( ++prt <= maxpr )
1581 printf("%.8x %.2x # %.8x %.2x\n", (unsigned)p1 - 1,
1582 p1[-1], (unsigned)p2 - 1, p2[-1]);
1584 printf("Total of %d differences\n", prt);
1587 static unsigned mend;
1588 static unsigned mask;
1594 unsigned char val[4];
1598 if (termch != '\n') {
1601 if (termch != '\n') {
1605 if (termch != '\n') termch = 0;
1610 for (a = mdest; a < mend; a += 4) {
1611 if (mread(a, val, 4) == 4
1612 && ((GETWORD(val) ^ mval) & mask) == 0) {
1613 printf("%.8x: %.8x\n", a, GETWORD(val));
1620 static unsigned mskip = 0x1000;
1621 static unsigned mlim = 0xffffffff;
1631 if (termch != '\n') termch = 0;
1633 if (termch != '\n') termch = 0;
1636 for (a = mdest; a < mlim; a += mskip) {
1637 ok = mread(a, &v, 1);
1639 printf("%.8x .. ", a);
1641 } else if (!ok && ook)
1642 printf("%.8x\n", a - mskip);
1648 printf("%.8x\n", a - mskip);
1653 unsigned int args[8];
1656 typedef unsigned int (*callfunc_t)(unsigned int, unsigned int,
1657 unsigned int, unsigned int, unsigned int,
1658 unsigned int, unsigned int, unsigned int);
1664 for (i = 0; i < 8; ++i)
1666 for (i = 0; i < 8; ++i) {
1667 if (!scanhex(&args[i]) || termch == '\n')
1671 func = (callfunc_t) adrs;
1673 if (setjmp(bus_error_jmp) == 0) {
1674 debugger_fault_handler = handle_fault;
1676 ret = func(args[0], args[1], args[2], args[3],
1677 args[4], args[5], args[6], args[7]);
1679 printf("return value is %x\n", ret);
1681 printf("*** %x exception occurred\n", fault_except);
1683 debugger_fault_handler = NULL;
1686 /* Input scanning routines */
1697 while( c == ' ' || c == '\t' )
1703 static char *regnames[N_PTREGS] = {
1704 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
1705 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
1706 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
1707 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
1708 "pc", "msr", "or3", "ctr", "lr", "xer", "ccr", "mq",
1709 "trap", "dar", "dsisr", "res"
1713 scanhex(unsigned *vp)
1720 /* parse register name */
1724 for (i = 0; i < sizeof(regname) - 1; ++i) {
1733 for (i = 0; i < N_PTREGS; ++i) {
1734 if (strcmp(regnames[i], regname) == 0) {
1735 unsigned *rp = (unsigned *)
1736 xmon_regs[smp_processor_id()];
1738 printf("regs not available\n");
1745 printf("invalid register name '%%%s'\n", regname);
1747 } else if (c == '$') {
1748 static char symname[128];
1750 for (i=0; i<63; i++) {
1760 if (setjmp(bus_error_jmp) == 0) {
1761 debugger_fault_handler = handle_fault;
1763 *vp = kallsyms_lookup_name(symname);
1766 debugger_fault_handler = NULL;
1768 printf("unknown symbol\n");
1784 } while( d != EOF );
1803 if( '0' <= c && c <= '9' )
1805 if( 'A' <= c && c <= 'F' )
1806 return c - ('A' - 10);
1807 if( 'a' <= c && c <= 'f' )
1808 return c - ('a' - 10);
1813 getstring(char *s, int size)
1824 } while( c != ' ' && c != '\t' && c != '\n' );
1829 static char line[256];
1830 static char *lineptr;
1841 if (lineptr == NULL || *lineptr == 0) {
1842 if (fgets(line, sizeof(line), stdin) == NULL) {
1852 take_input(char *str)
1860 int type = inchar();
1862 static char tmp[128];
1867 xmon_print_symbol(addr, ": ", "\n");
1872 if (setjmp(bus_error_jmp) == 0) {
1873 debugger_fault_handler = handle_fault;
1875 addr = kallsyms_lookup_name(tmp);
1877 printf("%s: %lx\n", tmp, addr);
1879 printf("Symbol '%s' not found.\n", tmp);
1882 debugger_fault_handler = NULL;