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 <asm/ptrace.h>
11 #include <asm/string.h>
13 #include <asm/bitops.h>
14 #include <asm/bootx.h>
15 #ifdef CONFIG_PMAC_BACKLIGHT
16 #include <asm/backlight.h>
23 #define scanhex xmon_scanhex
24 #define skipbl xmon_skipbl
27 static unsigned long cpus_in_xmon = 0;
28 static unsigned long got_xmon = 0;
29 static volatile int take_xmon = -1;
30 static int xmon_owner = -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);
109 extern int print_insn_big_powerpc(FILE *, unsigned long, unsigned);
110 extern void printf(const char *fmt, ...);
111 extern int putchar(int ch);
112 extern int setjmp(u_int *);
113 extern void longjmp(u_int *, int);
115 extern void xmon_enter(void);
116 extern void xmon_leave(void);
117 extern char* xmon_find_symbol(unsigned long addr, unsigned long* saddr);
118 extern unsigned long xmon_symbol_to_addr(char* symbol);
120 #define GETWORD(v) (((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
122 #define isxdigit(c) (('0' <= (c) && (c) <= '9') \
123 || ('a' <= (c) && (c) <= 'f') \
124 || ('A' <= (c) && (c) <= 'F'))
125 #define isalnum(c) (('0' <= (c) && (c) <= '9') \
126 || ('a' <= (c) && (c) <= 'z') \
127 || ('A' <= (c) && (c) <= 'Z'))
128 #define isspace(c) (c == ' ' || c == '\t' || c == 10 || c == 13 || c == 0)
130 static char *help_string = "\
133 di dump instructions\n\
134 df dump float values\n\
135 dd dump double values\n\
136 e print exception information\n\
138 m examine/change memory\n\
139 mm move a block of memory\n\
140 ms set a block of memory\n\
141 md compare two blocks of memory\n\
142 M print System.map\n\
144 S print special registers\n\
146 la lookup address in system.map\n\
147 ls lookup symbol in system.map\n\
151 static int xmon_trace[NR_CPUS];
152 #define SSTEP 1 /* stepping because of 's' command */
153 #define BRSTEP 2 /* stepping over breakpoint */
155 static struct pt_regs *xmon_regs[NR_CPUS];
157 extern inline void sync(void)
159 asm volatile("sync; isync");
162 extern inline void __delay(unsigned int loops)
165 __asm__ __volatile__("mtctr %0; 1: bdnz 1b" : :
166 "r" (loops) : "ctr");
171 xmon(struct pt_regs *excp)
177 asm volatile ("stw 0,0(%0)\n\
180 stmw 2,8(%0)" : : "b" (®s));
181 regs.nip = regs.link = ((unsigned long *)regs.gpr[1])[1];
182 regs.msr = get_msr();
183 regs.ctr = get_ctr();
184 regs.xer = get_xer();
191 set_msr(msr & ~0x8000); /* disable interrupts */
192 xmon_regs[smp_processor_id()] = excp;
196 set_bit(smp_processor_id(), &cpus_in_xmon);
197 if (smp_processor_id() != xmon_owner) {
198 while (test_and_set_bit(0, &got_xmon)) {
199 if (take_xmon == smp_processor_id()) {
204 xmon_owner = smp_processor_id();
207 * XXX: breakpoints are removed while any cpu is in xmon
209 #endif /* CONFIG_SMP */
211 #ifdef CONFIG_PMAC_BACKLIGHT
212 if( setjmp(bus_error_jmp) == 0 ) {
213 debugger_fault_handler = handle_fault;
215 set_backlight_enable(1);
216 set_backlight_level(BACKLIGHT_MAX);
219 debugger_fault_handler = 0;
220 #endif /* CONFIG_PMAC_BACKLIGHT */
223 xmon_trace[smp_processor_id()] = SSTEP;
225 } else if (at_breakpoint(excp->nip)) {
226 xmon_trace[smp_processor_id()] = BRSTEP;
229 xmon_trace[smp_processor_id()] = 0;
233 xmon_regs[smp_processor_id()] = 0;
235 clear_bit(0, &got_xmon);
237 clear_bit(smp_processor_id(), &cpus_in_xmon);
238 #endif /* CONFIG_SMP */
239 set_msr(msr); /* restore interrupt enable */
243 xmon_irq(int irq, void *d, struct pt_regs *regs)
248 printf("Keyboard interrupt\n");
250 __restore_flags(flags);
254 xmon_bpt(struct pt_regs *regs)
258 bp = at_breakpoint(regs->nip);
265 xmon_trace[smp_processor_id()] = BRSTEP;
274 xmon_sstep(struct pt_regs *regs)
276 if (!xmon_trace[smp_processor_id()])
278 if (xmon_trace[smp_processor_id()] == BRSTEP) {
279 xmon_trace[smp_processor_id()] = 0;
288 xmon_dabr_match(struct pt_regs *regs)
290 if (dabr.enabled && dabr.count) {
294 xmon_trace[smp_processor_id()] = BRSTEP;
297 dabr.instr = regs->nip;
304 xmon_iabr_match(struct pt_regs *regs)
306 if (iabr.enabled && iabr.count) {
310 xmon_trace[smp_processor_id()] = BRSTEP;
319 at_breakpoint(unsigned pc)
324 if (dabr.enabled && pc == dabr.instr)
326 if (iabr.enabled && pc == iabr.address)
329 for (i = 0; i < NBPTS; ++i, ++bp)
330 if (bp->enabled && pc == bp->address)
342 for (i = 0; i < NBPTS; ++i, ++bp) {
345 if (mread(bp->address, &bp->instr, 4) != 4
346 || mwrite(bp->address, &bpinstr, 4) != 4) {
347 printf("Couldn't insert breakpoint at %x, disabling\n",
351 store_inst((void *) bp->address);
353 #if !defined(CONFIG_8xx) && !defined(CONFIG_POWER4)
355 set_dabr(dabr.address);
357 set_iabr(iabr.address);
368 #if !defined(CONFIG_8xx) && !defined(CONFIG_POWER4)
373 for (i = 0; i < NBPTS; ++i, ++bp) {
376 if (mread(bp->address, &instr, 4) == 4
378 && mwrite(bp->address, &bp->instr, 4) != 4)
379 printf("Couldn't remove breakpoint at %x\n",
381 store_inst((void *) bp->address);
385 static char *last_cmd;
387 /* Command interpreting routine */
389 cmds(struct pt_regs *excp)
396 printf("%d:", smp_processor_id());
397 #endif /* CONFIG_SMP */
404 if (last_cmd == NULL)
406 take_input(last_cmd);
438 prregs(excp); /* print regs */
442 printf("No exception information\n");
469 printf("Unrecognized command: ");
470 if( ' ' < cmd && cmd <= '~' )
473 printf("\\x%x", cmd);
474 printf(" (type ? for help)\n");
486 #endif /* CONFIG_SMP */
492 static void cpu_cmd(void)
500 /* interrupt other cpu(s) */
501 cpu = MSG_ALL_BUT_SELF;
503 smp_send_xmon_break(cpu);
507 if (!scanhex(&cpu)) {
508 /* print cpus waiting or in xmon */
509 printf("cpus stopped:");
510 for (cpu = 0; cpu < NR_CPUS; ++cpu) {
511 if (test_bit(cpu, &cpus_in_xmon)) {
513 if (cpu == smp_processor_id())
520 /* try to switch to cpu specified */
524 while (take_xmon >= 0) {
525 if (--timeout == 0) {
526 /* yes there's a race here */
528 xmon_owner = smp_processor_id();
529 printf("cpu %u didn't take control\n", cpu);
533 /* now have to wait to be given control back */
534 while (test_and_set_bit(0, &got_xmon)) {
535 if (take_xmon == smp_processor_id()) {
537 xmon_owner = smp_processor_id();
542 #endif /* CONFIG_SMP */
544 static unsigned short fcstab[256] = {
545 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
546 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
547 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
548 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
549 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
550 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
551 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
552 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
553 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
554 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
555 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
556 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
557 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
558 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
559 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
560 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
561 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
562 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
563 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
564 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
565 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
566 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
567 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
568 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
569 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
570 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
571 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
572 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
573 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
574 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
575 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
576 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
579 #define FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
590 if (!scanhex(&ncsum))
593 for (i = 0; i < ncsum; ++i) {
594 if (mread(adrs+i, &v, 1) == 0) {
595 printf("csum stopped at %x\n", adrs+i);
613 #if !defined(CONFIG_8xx) && !defined(CONFIG_POWER4)
630 dabr.enabled = scanhex(&dabr.address);
631 scanhex(&dabr.count);
633 dabr.address = (dabr.address & ~7) | mode;
643 iabr.enabled = scanhex(&iabr.address);
645 iabr.address |= mode;
646 scanhex(&iabr.count);
651 /* clear all breakpoints */
652 for (i = 0; i < NBPTS; ++i)
656 printf("All breakpoints cleared\n");
658 bp = at_breakpoint(a);
660 printf("No breakpoint at %x\n", a);
669 /* print all breakpoints */
670 printf("type address count\n");
672 printf("data %.8x %8x [", dabr.address & ~7,
674 if (dabr.address & 1)
676 if (dabr.address & 2)
678 if (dabr.address & 4)
683 printf("inst %.8x %8x\n", iabr.address & ~3,
685 for (bp = bpts; bp < &bpts[NBPTS]; ++bp)
687 printf("trap %.8x %8x\n", bp->address,
691 bp = at_breakpoint(a);
693 for (bp = bpts; bp < &bpts[NBPTS]; ++bp)
696 if (bp >= &bpts[NBPTS]) {
697 printf("Sorry, no free breakpoints\n");
710 backtrace(struct pt_regs *excp)
715 extern char ret_from_intercept, ret_from_syscall_1, ret_from_syscall_2;
716 extern char do_signal_ret, ret_from_except;
718 printf("backtrace:\n");
726 for (; sp != 0; sp = stack[0]) {
727 if (mread(sp, stack, sizeof(stack)) != sizeof(stack))
729 pretty_print_addr(stack[1]);
731 if (stack[1] == (unsigned) &ret_from_intercept
732 || stack[1] == (unsigned) &ret_from_except
733 || stack[1] == (unsigned) &ret_from_syscall_1
734 || stack[1] == (unsigned) &ret_from_syscall_2
735 || stack[1] == (unsigned) &do_signal_ret) {
736 if (mread(sp+16, ®s, sizeof(regs)) != sizeof(regs))
738 printf("\nexception:%x [%x] %x ", regs.trap, sp+16,
741 if (mread(sp, stack, sizeof(stack)) != sizeof(stack))
753 asm("mr %0,1" : "=r" (x) :);
758 excprint(struct pt_regs *fp)
761 printf("cpu %d: ", smp_processor_id());
762 #endif /* CONFIG_SMP */
763 printf("vector: %x at pc = ", fp->trap);
764 pretty_print_addr(fp->nip);
766 pretty_print_addr(fp->link);
767 printf("\nmsr = %x, sp = %x [%x]\n", fp->msr, fp->gpr[1], fp);
768 if (fp->trap == 0x300 || fp->trap == 0x600)
769 printf("dar = %x, dsisr = %x\n", fp->dar, fp->dsisr);
771 printf("current = %x, pid = %d, comm = %s\n",
772 current, current->pid, current->comm);
776 prregs(struct pt_regs *fp)
782 fp = (struct pt_regs *) base;
783 for (n = 0; n < 32; ++n)
784 printf("R%.2d = %.8x%s", n, fp->gpr[n],
785 (n & 3) == 3? "\n": " ");
786 printf("pc = %.8x msr = %.8x lr = %.8x cr = %.8x\n",
787 fp->nip, fp->msr, fp->link, fp->ccr);
788 printf("ctr = %.8x xer = %.8x trap = %4x\n",
789 fp->ctr, fp->xer, fp->trap);
806 nflush = (nflush + 31) / 32;
808 for (; nflush > 0; --nflush, adrs += 0x20)
809 cflush((void *) adrs);
811 for (; nflush > 0; --nflush, adrs += 0x20)
812 cinval((void *) adrs);
819 unsigned int instrs[2];
822 instrs[0] = 0x7c6002a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
823 instrs[1] = 0x4e800020;
825 store_inst(instrs+1);
826 code = (int (*)(void)) instrs;
831 write_spr(int n, unsigned int val)
833 unsigned int instrs[2];
834 int (*code)(unsigned int);
836 instrs[0] = 0x7c6003a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
837 instrs[1] = 0x4e800020;
839 store_inst(instrs+1);
840 code = (int (*)(unsigned int)) instrs;
844 static unsigned int regno;
845 extern char exc_prolog;
853 printf("System.map: \n");
854 if( setjmp(bus_error_jmp) == 0 ) {
855 debugger_fault_handler = handle_fault;
860 debugger_fault_handler = 0;
863 printf("No System.map\n");
874 printf("msr = %x, pvr = %x\n", get_msr(), get_pvr());
875 printf("sprg0-3 = %x %x %x %x\n", get_sprg0(), get_sprg1(),
876 get_sprg2(), get_sprg3());
877 printf("srr0 = %x, srr1 = %x\n", get_srr0(), get_srr1());
878 #ifdef CONFIG_PPC_STD_MMU
880 for (i = 0; i < 16; ++i)
881 printf(" %x", get_sr(i));
884 asm("mr %0,1" : "=r" (i) :);
885 printf("sp = %x ", i);
886 asm("mr %0,2" : "=r" (i) :);
887 printf("toc = %x\n", i);
894 val = read_spr(regno);
896 write_spr(regno, val);
899 printf("spr %x = %x\n", regno, read_spr(regno));
923 extern int (*prom_entry)(int *);
932 args[0] = (int) "interpret";
939 printf("error %x\n", args[4]);
943 #ifndef CONFIG_PPC_STD_MMU
947 printf("This CPU doesn't have a hash table.\n");
951 #ifndef CONFIG_PPC64BRIDGE
953 dump_hash_table_seg(unsigned seg, unsigned start, unsigned end)
956 unsigned long hsize = Hash_size;
958 unsigned v, va, last_va;
959 int found, last_found, i;
960 unsigned *hg, w1, last_w2, last_va0;
963 hmask = hsize / 64 - 1;
965 start = (start >> 12) & 0xffff;
966 end = (end >> 12) & 0xffff;
967 for (v = start; v < end; ++v) {
969 hg = htab + (((v ^ seg) & hmask) * 16);
970 w1 = 0x80000000 | (seg << 7) | (v >> 10);
971 for (i = 0; i < 8; ++i, hg += 2) {
979 hg = htab + ((~(v ^ seg) & hmask) * 16);
980 for (i = 0; i < 8; ++i, hg += 2) {
987 if (!(last_found && found && (hg[1] & ~0x180) == last_w2 + 4096)) {
989 if (last_va != last_va0)
990 printf(" ... %x", last_va);
994 printf("%x to %x", va, hg[1]);
1000 last_w2 = hg[1] & ~0x180;
1006 printf(" ... %x\n", last_va);
1009 #else /* CONFIG_PPC64BRIDGE */
1011 dump_hash_table_seg(unsigned seg, unsigned start, unsigned end)
1014 unsigned long hsize = Hash_size;
1015 unsigned long hmask;
1016 unsigned v, va, last_va;
1017 int found, last_found, i;
1018 unsigned *hg, w1, last_w2, last_va0;
1021 hmask = hsize / 128 - 1;
1023 start = (start >> 12) & 0xffff;
1024 end = (end >> 12) & 0xffff;
1025 for (v = start; v < end; ++v) {
1027 hg = htab + (((v ^ seg) & hmask) * 32);
1028 w1 = 1 | (seg << 12) | ((v & 0xf800) >> 4);
1029 for (i = 0; i < 8; ++i, hg += 4) {
1037 hg = htab + ((~(v ^ seg) & hmask) * 32);
1038 for (i = 0; i < 8; ++i, hg += 4) {
1045 if (!(last_found && found && (hg[3] & ~0x180) == last_w2 + 4096)) {
1047 if (last_va != last_va0)
1048 printf(" ... %x", last_va);
1052 printf("%x to %x", va, hg[3]);
1058 last_w2 = hg[3] & ~0x180;
1064 printf(" ... %x\n", last_va);
1066 #endif /* CONFIG_PPC64BRIDGE */
1068 static unsigned hash_ctx;
1069 static unsigned hash_start;
1070 static unsigned hash_end;
1076 unsigned seg_start, seg_end;
1082 hash_end = 0xfffff000;
1084 scanhex(&hash_start);
1086 printf("Mappings for context %x\n", hash_ctx);
1087 seg_start = hash_start;
1088 for (seg = hash_start >> 28; seg <= hash_end >> 28; ++seg) {
1089 seg_end = (seg << 28) | 0x0ffff000;
1090 if (seg_end > hash_end)
1092 dump_hash_table_seg((hash_ctx << 4) + (seg * 0x111),
1093 seg_start, seg_end);
1094 seg_start = seg_end + 0x1000;
1097 #endif /* CONFIG_PPC_STD_MMU */
1100 * Stuff for reading and writing memory safely
1104 mread(unsigned adrs, void *buf, int size)
1110 if( setjmp(bus_error_jmp) == 0 ){
1111 debugger_fault_handler = handle_fault;
1116 case 2: *(short *)q = *(short *)p; break;
1117 case 4: *(int *)q = *(int *)p; break;
1119 for( ; n < size; ++n ) {
1125 /* wait a little while to see if we get a machine check */
1129 debugger_fault_handler = 0;
1134 mwrite(unsigned adrs, void *buf, int size)
1140 if( setjmp(bus_error_jmp) == 0 ){
1141 debugger_fault_handler = handle_fault;
1146 case 2: *(short *)p = *(short *)q; break;
1147 case 4: *(int *)p = *(int *)q; break;
1149 for( ; n < size; ++n ) {
1157 printf("*** Error writing address %x\n", adrs + n);
1159 debugger_fault_handler = 0;
1163 static int fault_type;
1164 static char *fault_chars[] = { "--", "**", "##" };
1167 handle_fault(struct pt_regs *regs)
1169 fault_type = regs->trap == 0x200? 0: regs->trap == 0x300? 1: 2;
1170 longjmp(bus_error_jmp, 1);
1173 #define SWAP(a, b, t) ((t) = (a), (a) = (b), (b) = (t))
1176 byterev(unsigned char *val, int size)
1182 SWAP(val[0], val[1], t);
1185 SWAP(val[0], val[3], t);
1186 SWAP(val[1], val[2], t);
1197 int cmd, inc, i, nslash;
1199 unsigned char val[4];
1203 while ((cmd = skipbl()) != '\n') {
1205 case 'b': size = 1; break;
1206 case 'w': size = 2; break;
1207 case 'l': size = 4; break;
1208 case 'r': brev = !brev; break;
1209 case 'n': mnoread = 1; break;
1210 case '.': mnoread = 0; break;
1219 n = mread(adrs, val, size);
1220 printf("%.8x%c", adrs, brev? 'r': ' ');
1225 for (i = 0; i < n; ++i)
1226 printf("%.2x", val[i]);
1227 for (; i < size; ++i)
1228 printf("%s", fault_chars[fault_type]);
1235 for (i = 0; i < size; ++i)
1236 val[i] = n >> (i * 8);
1239 mwrite(adrs, val, size);
1252 else if( n == '\'' )
1254 for (i = 0; i < size; ++i)
1255 val[i] = n >> (i * 8);
1258 mwrite(adrs, val, size);
1292 adrs -= 1 << nslash;
1296 adrs += 1 << nslash;
1300 adrs += 1 << -nslash;
1304 adrs -= 1 << -nslash;
1338 case 'n': c = '\n'; break;
1339 case 'r': c = '\r'; break;
1340 case 'b': c = '\b'; break;
1341 case 't': c = '\t'; break;
1352 if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')
1361 adrs += ppc_inst_dump(adrs, nidump);
1367 prdump(adrs, ndump);
1374 prdump(unsigned adrs, int ndump)
1376 register int n, m, c, r, nr;
1377 unsigned char temp[16];
1379 for( n = ndump; n > 0; ){
1380 printf("%.8x", adrs);
1383 nr = mread(adrs, temp, r);
1385 for( m = 0; m < r; ++m ){
1386 putchar((m & 3) == 0 && m > 0? '.': ' ');
1388 printf("%.2x", temp[m]);
1390 printf("%s", fault_chars[fault_type]);
1395 for( m = 0; m < r; ++m ){
1398 putchar(' ' <= c && c <= '~'? c: '.');
1412 ppc_inst_dump(unsigned adr, int count)
1416 unsigned long inst, last_inst;
1417 unsigned char val[4];
1420 for (first_adr = adr; count > 0; --count, adr += 4){
1421 nr = mread(adr, val, 4);
1423 const char *x = fault_chars[fault_type];
1424 printf("%.8x %s%s%s%s\n", adr, x, x, x, x);
1427 inst = GETWORD(val);
1428 if (adr > first_adr && inst == last_inst) {
1437 printf("%.8x ", adr);
1438 printf("%.8x\t", inst);
1439 print_insn_big_powerpc(stdout, inst, adr); /* always returns 4 */
1442 return adr - first_adr;
1449 printf("0x%x", addr);
1453 * Memory operations - move, set, print differences
1455 static unsigned mdest; /* destination address */
1456 static unsigned msrc; /* source address */
1457 static unsigned mval; /* byte value to set memory to */
1458 static unsigned mcount; /* # bytes to affect */
1459 static unsigned mdiffs; /* max # differences to print */
1465 if( termch != '\n' )
1467 scanhex(cmd == 's'? &mval: &msrc);
1468 if( termch != '\n' )
1473 memmove((void *)mdest, (void *)msrc, mcount);
1476 memset((void *)mdest, mval, mcount);
1479 if( termch != '\n' )
1482 memdiffs((unsigned char *)mdest, (unsigned char *)msrc, mcount, mdiffs);
1488 memdiffs(unsigned char *p1, unsigned char *p2, unsigned nb, unsigned maxpr)
1493 for( n = nb; n > 0; --n )
1494 if( *p1++ != *p2++ )
1495 if( ++prt <= maxpr )
1496 printf("%.8x %.2x # %.8x %.2x\n", (unsigned)p1 - 1,
1497 p1[-1], (unsigned)p2 - 1, p2[-1]);
1499 printf("Total of %d differences\n", prt);
1502 static unsigned mend;
1503 static unsigned mask;
1509 unsigned char val[4];
1513 if (termch != '\n') {
1516 if (termch != '\n') {
1520 if (termch != '\n') termch = 0;
1525 for (a = mdest; a < mend; a += 4) {
1526 if (mread(a, val, 4) == 4
1527 && ((GETWORD(val) ^ mval) & mask) == 0) {
1528 printf("%.8x: %.8x\n", a, GETWORD(val));
1535 static unsigned mskip = 0x1000;
1536 static unsigned mlim = 0xffffffff;
1546 if (termch != '\n') termch = 0;
1548 if (termch != '\n') termch = 0;
1551 for (a = mdest; a < mlim; a += mskip) {
1552 ok = mread(a, &v, 1);
1554 printf("%.8x .. ", a);
1556 } else if (!ok && ook)
1557 printf("%.8x\n", a - mskip);
1563 printf("%.8x\n", a - mskip);
1566 /* Input scanning routines */
1577 while( c == ' ' || c == '\t' )
1583 static char *regnames[N_PTREGS] = {
1584 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
1585 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
1586 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
1587 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
1588 "pc", "msr", "or3", "ctr", "lr", "xer", "ccr", "mq",
1589 "trap", "dar", "dsisr", "res"
1601 /* parse register name */
1605 for (i = 0; i < sizeof(regname) - 1; ++i) {
1614 for (i = 0; i < N_PTREGS; ++i) {
1615 if (strcmp(regnames[i], regname) == 0) {
1616 unsigned *rp = (unsigned *)
1617 xmon_regs[smp_processor_id()];
1619 printf("regs not available\n");
1626 printf("invalid register name '%%%s'\n", regname);
1628 } else if (c == '$') {
1629 static char symname[64];
1631 for (i=0; i<63; i++) {
1640 *vp = xmon_symbol_to_addr(symname);
1642 printf("unknown symbol\n");
1658 } while( d != EOF );
1678 if( '0' <= c && c <= '9' )
1680 if( 'A' <= c && c <= 'F' )
1681 return c - ('A' - 10);
1682 if( 'a' <= c && c <= 'f' )
1683 return c - ('a' - 10);
1688 getstring(char *s, int size)
1699 } while( c != ' ' && c != '\t' && c != '\n' );
1704 static char line[256];
1705 static char *lineptr;
1716 if (lineptr == NULL || *lineptr == 0) {
1717 if (fgets(line, sizeof(line), stdin) == NULL) {
1736 int type = inchar();
1738 static char tmp[64];
1741 extern char *sysmap;
1742 extern unsigned long sysmap_size;
1743 if ( !sysmap || !sysmap_size )
1748 if (scanhex(&addr)) {
1749 pretty_print_addr(addr);
1756 if( setjmp(bus_error_jmp) == 0 ) {
1757 debugger_fault_handler = handle_fault;
1761 cur = strstr(cur, tmp);
1763 static char res[64];
1766 while(p > sysmap && *p != 10)
1770 while(*p && p < (sysmap + sysmap_size) && *p != 10)
1773 printf("%s\n", res);
1779 debugger_fault_handler = 0;
1786 pretty_print_addr(unsigned long addr)
1789 unsigned long saddr;
1791 printf("%08x", addr);
1792 sym = xmon_find_symbol(addr, &saddr);
1794 printf(" (%s+0x%x)", sym, addr-saddr);
1799 xmon_find_symbol(unsigned long addr, unsigned long* saddr)
1801 static char rbuffer[64];
1802 char *p, *ep, *limit;
1803 unsigned long prev, next;
1806 extern char *sysmap;
1807 extern unsigned long sysmap_size;
1808 if ( !sysmap || !sysmap_size )
1814 limit = p + sysmap_size;
1815 if( setjmp(bus_error_jmp) == 0 ) {
1816 debugger_fault_handler = handle_fault;
1819 next = simple_strtoul(p, &p, 16);
1820 if (next > addr && prev <= addr) {
1825 while(*p && p < limit && *p == 32)
1827 while(*p && p < limit && *p != 10 && (ep - rbuffer) < 63)
1832 debugger_fault_handler = 0;
1837 while(*p && p < limit && *p != 10)
1840 } while(*p && p < limit && next);
1844 debugger_fault_handler = 0;
1849 xmon_symbol_to_addr(char* symbol)
1856 extern char *sysmap;
1857 extern unsigned long sysmap_size;
1858 if ( !sysmap || !sysmap_size )
1861 if( setjmp(bus_error_jmp) == 0 ) {
1862 debugger_fault_handler = handle_fault;
1866 cur = strstr(cur, symbol);
1870 /* best match if equal, better match if
1873 if (cur == sysmap || *(cur-1) == ' ') {
1875 if (cur[strlen(symbol)] == 10)
1878 if (gd > goodness) {
1889 while(p > sysmap && *p != 10)
1892 result = simple_strtoul(p, &p, 16);
1896 debugger_fault_handler = 0;