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>
15 #include <asm/machdep.h>
20 #define scanhex xmon_scanhex
21 #define skipbl xmon_skipbl
24 static unsigned long cpus_in_xmon = 0;
25 static unsigned long got_xmon = 0;
26 static volatile int take_xmon = -1;
27 #endif /* CONFIG_SMP */
31 static unsigned ndump = 64;
32 static unsigned nidump = 16;
33 static unsigned ncsum = 4096;
36 static u_int bus_error_jmp[100];
37 #define setjmp xmon_setjmp
38 #define longjmp xmon_longjmp
40 /* Breakpoint stuff */
45 unsigned char enabled;
49 static struct bpt bpts[NBPTS];
50 static struct bpt dabr;
51 static struct bpt iabr;
52 static unsigned bpinstr = 0x7fe00008; /* trap */
55 extern void (*debugger_fault_handler)(struct pt_regs *);
56 static int cmds(struct pt_regs *);
57 static int mread(unsigned, void *, int);
58 static int mwrite(unsigned, void *, int);
59 static void handle_fault(struct pt_regs *);
60 static void byterev(unsigned char *, int);
61 static void memex(void);
62 static int bsesc(void);
63 static void dump(void);
64 static void prdump(unsigned, int);
66 static void prndump(unsigned, int);
67 static int nvreadb(unsigned);
69 static int ppc_inst_dump(unsigned, int);
70 void print_address(unsigned);
71 static int getsp(void);
72 static void dump_hash_table(void);
73 static void backtrace(struct pt_regs *);
74 static void excprint(struct pt_regs *);
75 static void prregs(struct pt_regs *);
76 static void memops(int);
77 static void memlocate(void);
78 static void memzcan(void);
79 static void memdiffs(unsigned char *, unsigned char *, unsigned, unsigned);
81 int scanhex(unsigned *valp);
82 static void scannl(void);
83 static int hexdigit(int);
84 void getstring(char *, int);
85 static void flush_input(void);
86 static int inchar(void);
87 static void take_input(char *);
88 /* static void openforth(void); */
89 static unsigned read_spr(int);
90 static void write_spr(int, unsigned);
91 static void super_regs(void);
92 static void symbol_lookup(void);
93 static void remove_bpts(void);
94 static void insert_bpts(void);
95 static struct bpt *at_breakpoint(unsigned pc);
96 static void bpt_cmds(void);
97 void cacheflush(void);
99 static void cpu_cmd(void);
100 #endif /* CONFIG_SMP */
101 static void csum(void);
102 static void bootcmds(void);
103 static void proccall(void);
104 static void printtime(void);
106 extern int print_insn_big_powerpc(FILE *, unsigned long, unsigned);
107 extern void printf(const char *fmt, ...);
108 extern int putchar(int ch);
109 extern int setjmp(u_int *);
110 extern void longjmp(u_int *, int);
112 extern void xmon_enter(void);
113 extern void xmon_leave(void);
115 static unsigned start_tb[NR_CPUS][2];
116 static unsigned stop_tb[NR_CPUS][2];
118 #define GETWORD(v) (((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
120 #define isxdigit(c) (('0' <= (c) && (c) <= '9') \
121 || ('a' <= (c) && (c) <= 'f') \
122 || ('A' <= (c) && (c) <= 'F'))
123 #define isalnum(c) (('0' <= (c) && (c) <= '9') \
124 || ('a' <= (c) && (c) <= 'z') \
125 || ('A' <= (c) && (c) <= 'Z'))
126 #define isspace(c) (c == ' ' || c == '\t' || c == 10 || c == 13 || c == 0)
128 static char *help_string = "\
131 di dump instructions\n\
132 df dump float values\n\
133 dd dump double values\n\
134 e print exception information\n\
136 m examine/change memory\n\
137 mm move a block of memory\n\
138 ms set a block of memory\n\
139 md compare two blocks of memory\n\
141 S print special registers\n\
146 p call function with arguments\n\
153 static int xmon_trace[NR_CPUS];
154 #define SSTEP 1 /* stepping because of 's' command */
155 #define BRSTEP 2 /* stepping over breakpoint */
157 static struct pt_regs *xmon_regs[NR_CPUS];
159 extern inline void sync(void)
161 asm volatile("sync; isync");
164 extern inline void __delay(unsigned int loops)
167 __asm__ __volatile__("mtctr %0; 1: bdnz 1b" : :
168 "r" (loops) : "ctr");
171 /* Print an address in numeric and symbolic form (if possible) */
172 static void xmon_print_symbol(unsigned long address, const char *mid,
176 const char *name = NULL;
177 unsigned long offset, size;
178 static char tmpstr[128];
180 printf("%.8lx", address);
181 if (setjmp(bus_error_jmp) == 0) {
182 debugger_fault_handler = handle_fault;
184 name = kallsyms_lookup(address, &size, &offset, &modname,
187 /* wait a little while to see if we get a machine check */
190 debugger_fault_handler = NULL;
193 printf("%s%s+%#lx/%#lx", mid, name, offset, size);
195 printf(" [%s]", modname);
200 static void get_tb(unsigned *p)
202 unsigned hi, lo, hiagain;
204 if ((get_pvr() >> 16) == 1)
208 asm volatile("mftbu %0; mftb %1; mftbu %2"
209 : "=r" (hi), "=r" (lo), "=r" (hiagain));
210 } while (hi != hiagain);
215 int xmon(struct pt_regs *excp)
220 get_tb(stop_tb[smp_processor_id()]);
222 asm volatile ("stw 0,0(%0)\n\
225 stmw 2,8(%0)" : : "b" (®s));
226 regs.nip = regs.link = ((unsigned long *)regs.gpr[1])[1];
227 regs.msr = get_msr();
228 regs.ctr = get_ctr();
229 regs.xer = get_xer();
236 set_msr(msr & ~0x8000); /* disable interrupts */
237 xmon_regs[smp_processor_id()] = excp;
241 if (test_and_set_bit(smp_processor_id(), &cpus_in_xmon))
244 while (test_and_set_bit(0, &got_xmon)) {
245 if (take_xmon == smp_processor_id()) {
251 * XXX: breakpoints are removed while any cpu is in xmon
253 #endif /* CONFIG_SMP */
257 xmon_trace[smp_processor_id()] = SSTEP;
259 } else if (at_breakpoint(excp->nip)) {
260 xmon_trace[smp_processor_id()] = BRSTEP;
263 xmon_trace[smp_processor_id()] = 0;
267 xmon_regs[smp_processor_id()] = NULL;
269 clear_bit(0, &got_xmon);
270 clear_bit(smp_processor_id(), &cpus_in_xmon);
271 #endif /* CONFIG_SMP */
272 set_msr(msr); /* restore interrupt enable */
273 get_tb(start_tb[smp_processor_id()]);
279 xmon_irq(int irq, void *d, struct pt_regs *regs)
282 local_irq_save(flags);
283 printf("Keyboard interrupt\n");
285 local_irq_restore(flags);
290 xmon_bpt(struct pt_regs *regs)
294 bp = at_breakpoint(regs->nip);
301 xmon_trace[smp_processor_id()] = BRSTEP;
310 xmon_sstep(struct pt_regs *regs)
312 if (!xmon_trace[smp_processor_id()])
314 if (xmon_trace[smp_processor_id()] == BRSTEP) {
315 xmon_trace[smp_processor_id()] = 0;
324 xmon_dabr_match(struct pt_regs *regs)
326 if (dabr.enabled && dabr.count) {
330 xmon_trace[smp_processor_id()] = BRSTEP;
333 dabr.instr = regs->nip;
340 xmon_iabr_match(struct pt_regs *regs)
342 if (iabr.enabled && iabr.count) {
346 xmon_trace[smp_processor_id()] = BRSTEP;
355 at_breakpoint(unsigned pc)
360 if (dabr.enabled && pc == dabr.instr)
362 if (iabr.enabled && pc == iabr.address)
365 for (i = 0; i < NBPTS; ++i, ++bp)
366 if (bp->enabled && pc == bp->address)
378 for (i = 0; i < NBPTS; ++i, ++bp) {
381 if (mread(bp->address, &bp->instr, 4) != 4
382 || mwrite(bp->address, &bpinstr, 4) != 4) {
383 printf("Couldn't insert breakpoint at %x, disabling\n",
387 store_inst((void *) bp->address);
389 #if !defined(CONFIG_8xx)
391 set_dabr(dabr.address);
393 set_iabr(iabr.address);
404 #if !defined(CONFIG_8xx)
409 for (i = 0; i < NBPTS; ++i, ++bp) {
412 if (mread(bp->address, &instr, 4) == 4
414 && mwrite(bp->address, &bp->instr, 4) != 4)
415 printf("Couldn't remove breakpoint at %x\n",
417 store_inst((void *) bp->address);
421 static char *last_cmd;
423 /* Command interpreting routine */
425 cmds(struct pt_regs *excp)
432 printf("%d:", smp_processor_id());
433 #endif /* CONFIG_SMP */
440 if (last_cmd == NULL)
442 take_input(last_cmd);
474 prregs(excp); /* print regs */
478 printf("No exception information\n");
502 printf("Unrecognized command: ");
503 if( ' ' < cmd && cmd <= '~' )
506 printf("\\x%x", cmd);
507 printf(" (type ? for help)\n");
519 #endif /* CONFIG_SMP */
533 extern unsigned tb_to_us;
535 #define mulhwu(x,y) \
536 ({unsigned z; asm ("mulhwu %0,%1,%2" : "=r" (z) : "r" (x), "r" (y)); z;})
538 static void printtime(void)
542 delta = stop_tb[smp_processor_id()][1]
543 - start_tb[smp_processor_id()][1];
544 delta = mulhwu(tb_to_us, delta);
545 printf("%u.%06u seconds\n", delta / 1000000, delta % 1000000);
548 static void bootcmds(void)
554 ppc_md.restart(NULL);
562 static void cpu_cmd(void)
570 /* interrupt other cpu(s) */
571 cpu = MSG_ALL_BUT_SELF;
573 smp_send_xmon_break(cpu);
577 if (!scanhex(&cpu)) {
578 /* print cpus waiting or in xmon */
579 printf("cpus stopped:");
580 for (cpu = 0; cpu < NR_CPUS; ++cpu) {
581 if (test_bit(cpu, &cpus_in_xmon)) {
583 if (cpu == smp_processor_id())
590 /* try to switch to cpu specified */
593 while (take_xmon >= 0) {
594 if (--timeout == 0) {
595 /* yes there's a race here */
597 printf("cpu %u didn't take control\n", cpu);
601 /* now have to wait to be given control back */
602 while (test_and_set_bit(0, &got_xmon)) {
603 if (take_xmon == smp_processor_id()) {
609 #endif /* CONFIG_SMP */
612 static unsigned short fcstab[256] = {
613 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
614 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
615 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
616 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
617 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
618 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
619 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
620 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
621 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
622 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
623 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
624 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
625 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
626 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
627 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
628 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
629 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
630 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
631 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
632 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
633 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
634 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
635 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
636 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
637 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
638 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
639 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
640 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
641 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
642 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
643 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
644 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
647 #define FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
658 if (!scanhex(&ncsum))
661 for (i = 0; i < ncsum; ++i) {
662 if (mread(adrs+i, &v, 1) == 0) {
663 printf("csum stopped at %x\n", adrs+i);
681 #if !defined(CONFIG_8xx)
698 dabr.enabled = scanhex(&dabr.address);
699 scanhex(&dabr.count);
701 dabr.address = (dabr.address & ~7) | mode;
711 iabr.enabled = scanhex(&iabr.address);
713 iabr.address |= mode;
714 scanhex(&iabr.count);
719 /* clear all breakpoints */
720 for (i = 0; i < NBPTS; ++i)
724 printf("All breakpoints cleared\n");
726 bp = at_breakpoint(a);
728 printf("No breakpoint at %x\n", a);
737 /* print all breakpoints */
738 printf("type address count\n");
740 printf("data %.8x %8x [", dabr.address & ~7,
742 if (dabr.address & 1)
744 if (dabr.address & 2)
746 if (!(dabr.address & 4))
751 printf("inst %.8x %8x\n", iabr.address & ~3,
753 for (bp = bpts; bp < &bpts[NBPTS]; ++bp)
755 printf("trap %.8x %8x\n", bp->address,
759 bp = at_breakpoint(a);
761 for (bp = bpts; bp < &bpts[NBPTS]; ++bp)
764 if (bp >= &bpts[NBPTS]) {
765 printf("Sorry, no free breakpoints\n");
778 backtrace(struct pt_regs *excp)
783 extern char ret_from_except, ret_from_except_full, ret_from_syscall;
785 printf("backtrace:\n");
793 for (; sp != 0; sp = stack[0]) {
794 if (mread(sp, stack, sizeof(stack)) != sizeof(stack))
796 printf("[%.8lx] ", stack);
797 xmon_print_symbol(stack[1], " ", "\n");
798 if (stack[1] == (unsigned) &ret_from_except
799 || stack[1] == (unsigned) &ret_from_except_full
800 || stack[1] == (unsigned) &ret_from_syscall) {
801 if (mread(sp+16, ®s, sizeof(regs)) != sizeof(regs))
803 printf("exception:%x [%x] %x\n", regs.trap, sp+16,
806 if (mread(sp, stack, sizeof(stack)) != sizeof(stack))
817 asm("mr %0,1" : "=r" (x) :);
822 excprint(struct pt_regs *fp)
827 printf("cpu %d: ", smp_processor_id());
828 #endif /* CONFIG_SMP */
829 printf("vector: %x at pc=", fp->trap);
830 xmon_print_symbol(fp->nip, ": ", ", lr=");
831 xmon_print_symbol(fp->link, ": ", "\n");
832 printf("msr = %x, sp = %x [%x]\n", fp->msr, fp->gpr[1], fp);
834 if (trap == 0x300 || trap == 0x600)
835 printf("dar = %x, dsisr = %x\n", fp->dar, fp->dsisr);
837 printf("current = %x, pid = %d, comm = %s\n",
838 current, current->pid, current->comm);
842 prregs(struct pt_regs *fp)
848 fp = (struct pt_regs *) base;
849 for (n = 0; n < 32; ++n) {
850 printf("R%.2d = %.8x%s", n, fp->gpr[n],
851 (n & 3) == 3? "\n": " ");
852 if (n == 12 && !FULL_REGS(fp)) {
857 printf("pc = %.8x msr = %.8x lr = %.8x cr = %.8x\n",
858 fp->nip, fp->msr, fp->link, fp->ccr);
859 printf("ctr = %.8x xer = %.8x trap = %4x\n",
860 fp->ctr, fp->xer, fp->trap);
877 nflush = (nflush + 31) / 32;
879 for (; nflush > 0; --nflush, adrs += 0x20)
880 cflush((void *) adrs);
882 for (; nflush > 0; --nflush, adrs += 0x20)
883 cinval((void *) adrs);
890 unsigned int instrs[2];
893 instrs[0] = 0x7c6002a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
894 instrs[1] = 0x4e800020;
896 store_inst(instrs+1);
897 code = (int (*)(void)) instrs;
902 write_spr(int n, unsigned int val)
904 unsigned int instrs[2];
905 int (*code)(unsigned int);
907 instrs[0] = 0x7c6003a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
908 instrs[1] = 0x4e800020;
910 store_inst(instrs+1);
911 code = (int (*)(unsigned int)) instrs;
915 static unsigned int regno;
916 extern char exc_prolog;
927 printf("msr = %x, pvr = %x\n", get_msr(), get_pvr());
928 printf("sprg0-3 = %x %x %x %x\n", get_sprg0(), get_sprg1(),
929 get_sprg2(), get_sprg3());
930 printf("srr0 = %x, srr1 = %x\n", get_srr0(), get_srr1());
931 #ifdef CONFIG_PPC_STD_MMU
933 for (i = 0; i < 16; ++i)
934 printf(" %x", get_sr(i));
937 asm("mr %0,1" : "=r" (i) :);
938 printf("sp = %x ", i);
939 asm("mr %0,2" : "=r" (i) :);
940 printf("toc = %x\n", i);
947 val = read_spr(regno);
949 write_spr(regno, val);
952 printf("spr %x = %x\n", regno, read_spr(regno));
968 #ifndef CONFIG_PPC_STD_MMU
970 dump_hash_table(void)
972 printf("This CPU doesn't have a hash table.\n");
977 dump_hash_table_seg(unsigned seg, unsigned start, unsigned end)
980 extern unsigned long Hash_size;
981 unsigned *htab = Hash;
982 unsigned hsize = Hash_size;
983 unsigned v, hmask, va, last_va = 0;
984 int found, last_found, i;
985 unsigned *hg, w1, last_w2 = 0, last_va0 = 0;
988 hmask = hsize / 64 - 1;
990 start = (start >> 12) & 0xffff;
991 end = (end >> 12) & 0xffff;
992 for (v = start; v < end; ++v) {
994 hg = htab + (((v ^ seg) & hmask) * 16);
995 w1 = 0x80000000 | (seg << 7) | (v >> 10);
996 for (i = 0; i < 8; ++i, hg += 2) {
1004 hg = htab + ((~(v ^ seg) & hmask) * 16);
1005 for (i = 0; i < 8; ++i, hg += 2) {
1012 if (!(last_found && found && (hg[1] & ~0x180) == last_w2 + 4096)) {
1014 if (last_va != last_va0)
1015 printf(" ... %x", last_va);
1019 printf("%x to %x", va, hg[1]);
1025 last_w2 = hg[1] & ~0x180;
1031 printf(" ... %x\n", last_va);
1034 static unsigned hash_ctx;
1035 static unsigned hash_start;
1036 static unsigned hash_end;
1039 dump_hash_table(void)
1042 unsigned seg_start, seg_end;
1046 hash_end = 0xfffff000;
1048 scanhex(&hash_start);
1050 printf("Mappings for context %x\n", hash_ctx);
1051 seg_start = hash_start;
1052 for (seg = hash_start >> 28; seg <= hash_end >> 28; ++seg) {
1053 seg_end = (seg << 28) | 0x0ffff000;
1054 if (seg_end > hash_end)
1056 dump_hash_table_seg((hash_ctx << 4) + (seg * 0x111),
1057 seg_start, seg_end);
1058 seg_start = seg_end + 0x1000;
1061 #endif /* CONFIG_PPC_STD_MMU */
1064 * Stuff for reading and writing memory safely
1068 mread(unsigned adrs, void *buf, int size)
1074 if( setjmp(bus_error_jmp) == 0 ){
1075 debugger_fault_handler = handle_fault;
1080 case 2: *(short *)q = *(short *)p; break;
1081 case 4: *(int *)q = *(int *)p; break;
1083 for( ; n < size; ++n ) {
1089 /* wait a little while to see if we get a machine check */
1093 debugger_fault_handler = NULL;
1098 mwrite(unsigned adrs, void *buf, int size)
1104 if( setjmp(bus_error_jmp) == 0 ){
1105 debugger_fault_handler = handle_fault;
1110 case 2: *(short *)p = *(short *)q; break;
1111 case 4: *(int *)p = *(int *)q; break;
1113 for( ; n < size; ++n ) {
1121 printf("*** Error writing address %x\n", adrs + n);
1123 debugger_fault_handler = NULL;
1127 static int fault_type;
1128 static int fault_except;
1129 static char *fault_chars[] = { "--", "**", "##" };
1132 handle_fault(struct pt_regs *regs)
1134 fault_except = TRAP(regs);
1135 fault_type = TRAP(regs) == 0x200? 0: TRAP(regs) == 0x300? 1: 2;
1136 longjmp(bus_error_jmp, 1);
1139 #define SWAP(a, b, t) ((t) = (a), (a) = (b), (b) = (t))
1142 byterev(unsigned char *val, int size)
1148 SWAP(val[0], val[1], t);
1151 SWAP(val[0], val[3], t);
1152 SWAP(val[1], val[2], t);
1163 int cmd, inc, i, nslash;
1165 unsigned char val[4];
1169 while ((cmd = skipbl()) != '\n') {
1171 case 'b': size = 1; break;
1172 case 'w': size = 2; break;
1173 case 'l': size = 4; break;
1174 case 'r': brev = !brev; break;
1175 case 'n': mnoread = 1; break;
1176 case '.': mnoread = 0; break;
1185 n = mread(adrs, val, size);
1186 printf("%.8x%c", adrs, brev? 'r': ' ');
1191 for (i = 0; i < n; ++i)
1192 printf("%.2x", val[i]);
1193 for (; i < size; ++i)
1194 printf("%s", fault_chars[fault_type]);
1201 for (i = 0; i < size; ++i)
1202 val[i] = n >> (i * 8);
1205 mwrite(adrs, val, size);
1218 else if( n == '\'' )
1220 for (i = 0; i < size; ++i)
1221 val[i] = n >> (i * 8);
1224 mwrite(adrs, val, size);
1258 adrs -= 1 << nslash;
1262 adrs += 1 << nslash;
1266 adrs += 1 << -nslash;
1270 adrs -= 1 << -nslash;
1304 case 'n': c = '\n'; break;
1305 case 'r': c = '\r'; break;
1306 case 'b': c = '\b'; break;
1307 case 't': c = '\t'; break;
1318 if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')
1327 adrs += ppc_inst_dump(adrs, nidump);
1333 prdump(adrs, ndump);
1340 prdump(unsigned adrs, int ndump)
1342 register int n, m, c, r, nr;
1343 unsigned char temp[16];
1345 for( n = ndump; n > 0; ){
1346 printf("%.8x", adrs);
1349 nr = mread(adrs, temp, r);
1351 for( m = 0; m < r; ++m ){
1352 putchar((m & 3) == 0 && m > 0? '.': ' ');
1354 printf("%.2x", temp[m]);
1356 printf("%s", fault_chars[fault_type]);
1361 for( m = 0; m < r; ++m ){
1364 putchar(' ' <= c && c <= '~'? c: '.');
1378 ppc_inst_dump(unsigned adr, int count)
1382 unsigned long inst, last_inst = 0;
1383 unsigned char val[4];
1386 for (first_adr = adr; count > 0; --count, adr += 4){
1387 nr = mread(adr, val, 4);
1389 const char *x = fault_chars[fault_type];
1390 printf("%.8x %s%s%s%s\n", adr, x, x, x, x);
1393 inst = GETWORD(val);
1394 if (adr > first_adr && inst == last_inst) {
1403 printf("%.8x ", adr);
1404 printf("%.8x\t", inst);
1405 print_insn_big_powerpc(stdout, inst, adr); /* always returns 4 */
1408 return adr - first_adr;
1412 print_address(unsigned addr)
1414 printf("0x%x", addr);
1418 * Memory operations - move, set, print differences
1420 static unsigned mdest; /* destination address */
1421 static unsigned msrc; /* source address */
1422 static unsigned mval; /* byte value to set memory to */
1423 static unsigned mcount; /* # bytes to affect */
1424 static unsigned mdiffs; /* max # differences to print */
1430 if( termch != '\n' )
1432 scanhex(cmd == 's'? &mval: &msrc);
1433 if( termch != '\n' )
1438 memmove((void *)mdest, (void *)msrc, mcount);
1441 memset((void *)mdest, mval, mcount);
1444 if( termch != '\n' )
1447 memdiffs((unsigned char *)mdest, (unsigned char *)msrc, mcount, mdiffs);
1453 memdiffs(unsigned char *p1, unsigned char *p2, unsigned nb, unsigned maxpr)
1458 for( n = nb; n > 0; --n )
1459 if( *p1++ != *p2++ )
1460 if( ++prt <= maxpr )
1461 printf("%.8x %.2x # %.8x %.2x\n", (unsigned)p1 - 1,
1462 p1[-1], (unsigned)p2 - 1, p2[-1]);
1464 printf("Total of %d differences\n", prt);
1467 static unsigned mend;
1468 static unsigned mask;
1474 unsigned char val[4];
1478 if (termch != '\n') {
1481 if (termch != '\n') {
1485 if (termch != '\n') termch = 0;
1490 for (a = mdest; a < mend; a += 4) {
1491 if (mread(a, val, 4) == 4
1492 && ((GETWORD(val) ^ mval) & mask) == 0) {
1493 printf("%.8x: %.8x\n", a, GETWORD(val));
1500 static unsigned mskip = 0x1000;
1501 static unsigned mlim = 0xffffffff;
1511 if (termch != '\n') termch = 0;
1513 if (termch != '\n') termch = 0;
1516 for (a = mdest; a < mlim; a += mskip) {
1517 ok = mread(a, &v, 1);
1519 printf("%.8x .. ", a);
1521 } else if (!ok && ook)
1522 printf("%.8x\n", a - mskip);
1528 printf("%.8x\n", a - mskip);
1533 unsigned int args[8];
1536 typedef unsigned int (*callfunc_t)(unsigned int, unsigned int,
1537 unsigned int, unsigned int, unsigned int,
1538 unsigned int, unsigned int, unsigned int);
1544 for (i = 0; i < 8; ++i)
1546 for (i = 0; i < 8; ++i) {
1547 if (!scanhex(&args[i]) || termch == '\n')
1551 func = (callfunc_t) adrs;
1553 if (setjmp(bus_error_jmp) == 0) {
1554 debugger_fault_handler = handle_fault;
1556 ret = func(args[0], args[1], args[2], args[3],
1557 args[4], args[5], args[6], args[7]);
1559 printf("return value is %x\n", ret);
1561 printf("*** %x exception occurred\n", fault_except);
1563 debugger_fault_handler = NULL;
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"
1593 scanhex(unsigned *vp)
1600 /* parse register name */
1604 for (i = 0; i < sizeof(regname) - 1; ++i) {
1613 for (i = 0; i < N_PTREGS; ++i) {
1614 if (strcmp(regnames[i], regname) == 0) {
1615 unsigned *rp = (unsigned *)
1616 xmon_regs[smp_processor_id()];
1618 printf("regs not available\n");
1625 printf("invalid register name '%%%s'\n", regname);
1627 } else if (c == '$') {
1628 static char symname[128];
1630 for (i=0; i<63; i++) {
1640 if (setjmp(bus_error_jmp) == 0) {
1641 debugger_fault_handler = handle_fault;
1643 *vp = kallsyms_lookup_name(symname);
1646 debugger_fault_handler = NULL;
1648 printf("unknown symbol\n");
1664 } while( d != EOF );
1683 if( '0' <= c && c <= '9' )
1685 if( 'A' <= c && c <= 'F' )
1686 return c - ('A' - 10);
1687 if( 'a' <= c && c <= 'f' )
1688 return c - ('a' - 10);
1693 getstring(char *s, int size)
1704 } while( c != ' ' && c != '\t' && c != '\n' );
1709 static char line[256];
1710 static char *lineptr;
1721 if (lineptr == NULL || *lineptr == 0) {
1722 if (fgets(line, sizeof(line), stdin) == NULL) {
1732 take_input(char *str)
1740 int type = inchar();
1742 static char tmp[128];
1747 xmon_print_symbol(addr, ": ", "\n");
1752 if (setjmp(bus_error_jmp) == 0) {
1753 debugger_fault_handler = handle_fault;
1755 addr = kallsyms_lookup_name(tmp);
1757 printf("%s: %lx\n", tmp, addr);
1759 printf("Symbol '%s' not found.\n", tmp);
1762 debugger_fault_handler = NULL;