2 * Routines providing a simple monitor for use on the PowerMac.
4 * Copyright (C) 1996 Paul Mackerras.
6 #include <linux/errno.h>
7 #include <linux/sched.h>
9 #include <linux/interrupt.h>
10 #include <linux/bitops.h>
11 #include <linux/kallsyms.h>
12 #include <asm/ptrace.h>
13 #include <asm/string.h>
14 #include <asm/machdep.h>
19 #define scanhex xmon_scanhex
20 #define skipbl xmon_skipbl
23 static unsigned long cpus_in_xmon = 0;
24 static unsigned long got_xmon = 0;
25 static volatile int take_xmon = -1;
26 #endif /* CONFIG_SMP */
30 static unsigned ndump = 64;
31 static unsigned nidump = 16;
32 static unsigned ncsum = 4096;
35 static u_int bus_error_jmp[100];
36 #define setjmp xmon_setjmp
37 #define longjmp xmon_longjmp
39 /* Breakpoint stuff */
44 unsigned char enabled;
48 static struct bpt bpts[NBPTS];
49 static struct bpt dabr;
50 static struct bpt iabr;
51 static unsigned bpinstr = 0x7fe00008; /* trap */
54 extern void (*debugger_fault_handler)(struct pt_regs *);
55 static int cmds(struct pt_regs *);
56 static int mread(unsigned, void *, int);
57 static int mwrite(unsigned, void *, int);
58 static void handle_fault(struct pt_regs *);
59 static void byterev(unsigned char *, int);
60 static void memex(void);
61 static int bsesc(void);
62 static void dump(void);
63 static void prdump(unsigned, int);
65 static void prndump(unsigned, int);
66 static int nvreadb(unsigned);
68 static int ppc_inst_dump(unsigned, int);
69 void print_address(unsigned);
70 static int getsp(void);
71 static void dump_hash_table(void);
72 static void backtrace(struct pt_regs *);
73 static void excprint(struct pt_regs *);
74 static void prregs(struct pt_regs *);
75 static void memops(int);
76 static void memlocate(void);
77 static void memzcan(void);
78 static void memdiffs(unsigned char *, unsigned char *, unsigned, unsigned);
80 int scanhex(unsigned *valp);
81 static void scannl(void);
82 static int hexdigit(int);
83 void getstring(char *, int);
84 static void flush_input(void);
85 static int inchar(void);
86 static void take_input(char *);
87 /* static void openforth(void); */
88 static unsigned read_spr(int);
89 static void write_spr(int, unsigned);
90 static void super_regs(void);
91 static void symbol_lookup(void);
92 static void remove_bpts(void);
93 static void insert_bpts(void);
94 static struct bpt *at_breakpoint(unsigned pc);
95 static void bpt_cmds(void);
96 void cacheflush(void);
98 static void cpu_cmd(void);
99 #endif /* CONFIG_SMP */
100 static void csum(void);
101 static void bootcmds(void);
102 static void proccall(void);
103 static void printtime(void);
105 extern int print_insn_big_powerpc(FILE *, unsigned long, unsigned);
106 extern void printf(const char *fmt, ...);
107 extern int putchar(int ch);
108 extern int setjmp(u_int *);
109 extern void longjmp(u_int *, int);
111 extern void xmon_enter(void);
112 extern void xmon_leave(void);
114 static unsigned start_tb[NR_CPUS][2];
115 static unsigned stop_tb[NR_CPUS][2];
117 #define GETWORD(v) (((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
119 #define isxdigit(c) (('0' <= (c) && (c) <= '9') \
120 || ('a' <= (c) && (c) <= 'f') \
121 || ('A' <= (c) && (c) <= 'F'))
122 #define isalnum(c) (('0' <= (c) && (c) <= '9') \
123 || ('a' <= (c) && (c) <= 'z') \
124 || ('A' <= (c) && (c) <= 'Z'))
125 #define isspace(c) (c == ' ' || c == '\t' || c == 10 || c == 13 || c == 0)
127 static char *help_string = "\
130 di dump instructions\n\
131 df dump float values\n\
132 dd dump double values\n\
133 e print exception information\n\
135 m examine/change memory\n\
136 mm move a block of memory\n\
137 ms set a block of memory\n\
138 md compare two blocks of memory\n\
140 S print special registers\n\
145 p call function with arguments\n\
152 static int xmon_trace[NR_CPUS];
153 #define SSTEP 1 /* stepping because of 's' command */
154 #define BRSTEP 2 /* stepping over breakpoint */
156 static struct pt_regs *xmon_regs[NR_CPUS];
158 extern inline void sync(void)
160 asm volatile("sync; isync");
163 extern inline void __delay(unsigned int loops)
166 __asm__ __volatile__("mtctr %0; 1: bdnz 1b" : :
167 "r" (loops) : "ctr");
170 /* Print an address in numeric and symbolic form (if possible) */
171 static void xmon_print_symbol(unsigned long address, const char *mid,
175 const char *name = NULL;
176 unsigned long offset, size;
177 static char tmpstr[128];
179 printf("%.8lx", address);
180 if (setjmp(bus_error_jmp) == 0) {
181 debugger_fault_handler = handle_fault;
183 name = kallsyms_lookup(address, &size, &offset, &modname,
186 /* wait a little while to see if we get a machine check */
189 debugger_fault_handler = NULL;
192 printf("%s%s+%#lx/%#lx", mid, name, offset, size);
194 printf(" [%s]", modname);
199 static void get_tb(unsigned *p)
201 unsigned hi, lo, hiagain;
203 if ((get_pvr() >> 16) == 1)
207 asm volatile("mftbu %0; mftb %1; mftbu %2"
208 : "=r" (hi), "=r" (lo), "=r" (hiagain));
209 } while (hi != hiagain);
214 int xmon(struct pt_regs *excp)
219 get_tb(stop_tb[smp_processor_id()]);
221 asm volatile ("stw 0,0(%0)\n\
224 stmw 2,8(%0)" : : "b" (®s));
225 regs.nip = regs.link = ((unsigned long *)regs.gpr[1])[1];
226 regs.msr = get_msr();
227 regs.ctr = get_ctr();
228 regs.xer = get_xer();
235 set_msr(msr & ~0x8000); /* disable interrupts */
236 xmon_regs[smp_processor_id()] = excp;
240 if (test_and_set_bit(smp_processor_id(), &cpus_in_xmon))
243 while (test_and_set_bit(0, &got_xmon)) {
244 if (take_xmon == smp_processor_id()) {
250 * XXX: breakpoints are removed while any cpu is in xmon
252 #endif /* CONFIG_SMP */
256 xmon_trace[smp_processor_id()] = SSTEP;
258 } else if (at_breakpoint(excp->nip)) {
259 xmon_trace[smp_processor_id()] = BRSTEP;
262 xmon_trace[smp_processor_id()] = 0;
266 xmon_regs[smp_processor_id()] = NULL;
268 clear_bit(0, &got_xmon);
269 clear_bit(smp_processor_id(), &cpus_in_xmon);
270 #endif /* CONFIG_SMP */
271 set_msr(msr); /* restore interrupt enable */
272 get_tb(start_tb[smp_processor_id()]);
278 xmon_irq(int irq, void *d, struct pt_regs *regs)
281 local_irq_save(flags);
282 printf("Keyboard interrupt\n");
284 local_irq_restore(flags);
289 xmon_bpt(struct pt_regs *regs)
293 bp = at_breakpoint(regs->nip);
300 xmon_trace[smp_processor_id()] = BRSTEP;
309 xmon_sstep(struct pt_regs *regs)
311 if (!xmon_trace[smp_processor_id()])
313 if (xmon_trace[smp_processor_id()] == BRSTEP) {
314 xmon_trace[smp_processor_id()] = 0;
323 xmon_dabr_match(struct pt_regs *regs)
325 if (dabr.enabled && dabr.count) {
329 xmon_trace[smp_processor_id()] = BRSTEP;
332 dabr.instr = regs->nip;
339 xmon_iabr_match(struct pt_regs *regs)
341 if (iabr.enabled && iabr.count) {
345 xmon_trace[smp_processor_id()] = BRSTEP;
354 at_breakpoint(unsigned pc)
359 if (dabr.enabled && pc == dabr.instr)
361 if (iabr.enabled && pc == iabr.address)
364 for (i = 0; i < NBPTS; ++i, ++bp)
365 if (bp->enabled && pc == bp->address)
377 for (i = 0; i < NBPTS; ++i, ++bp) {
380 if (mread(bp->address, &bp->instr, 4) != 4
381 || mwrite(bp->address, &bpinstr, 4) != 4) {
382 printf("Couldn't insert breakpoint at %x, disabling\n",
386 store_inst((void *) bp->address);
388 #if !defined(CONFIG_8xx)
390 set_dabr(dabr.address);
392 set_iabr(iabr.address);
403 #if !defined(CONFIG_8xx)
408 for (i = 0; i < NBPTS; ++i, ++bp) {
411 if (mread(bp->address, &instr, 4) == 4
413 && mwrite(bp->address, &bp->instr, 4) != 4)
414 printf("Couldn't remove breakpoint at %x\n",
416 store_inst((void *) bp->address);
420 static char *last_cmd;
422 /* Command interpreting routine */
424 cmds(struct pt_regs *excp)
431 printf("%d:", smp_processor_id());
432 #endif /* CONFIG_SMP */
439 if (last_cmd == NULL)
441 take_input(last_cmd);
473 prregs(excp); /* print regs */
477 printf("No exception information\n");
501 printf("Unrecognized command: ");
502 if( ' ' < cmd && cmd <= '~' )
505 printf("\\x%x", cmd);
506 printf(" (type ? for help)\n");
518 #endif /* CONFIG_SMP */
532 extern unsigned tb_to_us;
534 #define mulhwu(x,y) \
535 ({unsigned z; asm ("mulhwu %0,%1,%2" : "=r" (z) : "r" (x), "r" (y)); z;})
537 static void printtime(void)
541 delta = stop_tb[smp_processor_id()][1]
542 - start_tb[smp_processor_id()][1];
543 delta = mulhwu(tb_to_us, delta);
544 printf("%u.%06u seconds\n", delta / 1000000, delta % 1000000);
547 static void bootcmds(void)
553 ppc_md.restart(NULL);
561 static void cpu_cmd(void)
569 /* interrupt other cpu(s) */
570 cpu = MSG_ALL_BUT_SELF;
572 smp_send_xmon_break(cpu);
576 if (!scanhex(&cpu)) {
577 /* print cpus waiting or in xmon */
578 printf("cpus stopped:");
579 for (cpu = 0; cpu < NR_CPUS; ++cpu) {
580 if (test_bit(cpu, &cpus_in_xmon)) {
582 if (cpu == smp_processor_id())
589 /* try to switch to cpu specified */
592 while (take_xmon >= 0) {
593 if (--timeout == 0) {
594 /* yes there's a race here */
596 printf("cpu %u didn't take control\n", cpu);
600 /* now have to wait to be given control back */
601 while (test_and_set_bit(0, &got_xmon)) {
602 if (take_xmon == smp_processor_id()) {
608 #endif /* CONFIG_SMP */
611 static unsigned short fcstab[256] = {
612 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
613 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
614 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
615 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
616 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
617 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
618 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
619 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
620 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
621 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
622 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
623 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
624 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
625 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
626 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
627 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
628 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
629 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
630 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
631 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
632 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
633 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
634 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
635 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
636 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
637 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
638 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
639 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
640 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
641 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
642 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
643 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
646 #define FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
657 if (!scanhex(&ncsum))
660 for (i = 0; i < ncsum; ++i) {
661 if (mread(adrs+i, &v, 1) == 0) {
662 printf("csum stopped at %x\n", adrs+i);
680 #if !defined(CONFIG_8xx)
697 dabr.enabled = scanhex(&dabr.address);
698 scanhex(&dabr.count);
700 dabr.address = (dabr.address & ~7) | mode;
710 iabr.enabled = scanhex(&iabr.address);
712 iabr.address |= mode;
713 scanhex(&iabr.count);
718 /* clear all breakpoints */
719 for (i = 0; i < NBPTS; ++i)
723 printf("All breakpoints cleared\n");
725 bp = at_breakpoint(a);
727 printf("No breakpoint at %x\n", a);
736 /* print all breakpoints */
737 printf("type address count\n");
739 printf("data %.8x %8x [", dabr.address & ~7,
741 if (dabr.address & 1)
743 if (dabr.address & 2)
745 if (!(dabr.address & 4))
750 printf("inst %.8x %8x\n", iabr.address & ~3,
752 for (bp = bpts; bp < &bpts[NBPTS]; ++bp)
754 printf("trap %.8x %8x\n", bp->address,
758 bp = at_breakpoint(a);
760 for (bp = bpts; bp < &bpts[NBPTS]; ++bp)
763 if (bp >= &bpts[NBPTS]) {
764 printf("Sorry, no free breakpoints\n");
777 backtrace(struct pt_regs *excp)
782 extern char ret_from_except, ret_from_except_full, ret_from_syscall;
784 printf("backtrace:\n");
792 for (; sp != 0; sp = stack[0]) {
793 if (mread(sp, stack, sizeof(stack)) != sizeof(stack))
795 printf("[%.8lx] ", stack);
796 xmon_print_symbol(stack[1], " ", "\n");
797 if (stack[1] == (unsigned) &ret_from_except
798 || stack[1] == (unsigned) &ret_from_except_full
799 || stack[1] == (unsigned) &ret_from_syscall) {
800 if (mread(sp+16, ®s, sizeof(regs)) != sizeof(regs))
802 printf("exception:%x [%x] %x\n", regs.trap, sp+16,
805 if (mread(sp, stack, sizeof(stack)) != sizeof(stack))
816 asm("mr %0,1" : "=r" (x) :);
821 excprint(struct pt_regs *fp)
826 printf("cpu %d: ", smp_processor_id());
827 #endif /* CONFIG_SMP */
828 printf("vector: %x at pc=", fp->trap);
829 xmon_print_symbol(fp->nip, ": ", ", lr=");
830 xmon_print_symbol(fp->link, ": ", "\n");
831 printf("msr = %x, sp = %x [%x]\n", fp->msr, fp->gpr[1], fp);
833 if (trap == 0x300 || trap == 0x600)
834 printf("dar = %x, dsisr = %x\n", fp->dar, fp->dsisr);
836 printf("current = %x, pid = %d, comm = %s\n",
837 current, current->pid, current->comm);
841 prregs(struct pt_regs *fp)
847 fp = (struct pt_regs *) base;
848 for (n = 0; n < 32; ++n) {
849 printf("R%.2d = %.8x%s", n, fp->gpr[n],
850 (n & 3) == 3? "\n": " ");
851 if (n == 12 && !FULL_REGS(fp)) {
856 printf("pc = %.8x msr = %.8x lr = %.8x cr = %.8x\n",
857 fp->nip, fp->msr, fp->link, fp->ccr);
858 printf("ctr = %.8x xer = %.8x trap = %4x\n",
859 fp->ctr, fp->xer, fp->trap);
876 nflush = (nflush + 31) / 32;
878 for (; nflush > 0; --nflush, adrs += 0x20)
879 cflush((void *) adrs);
881 for (; nflush > 0; --nflush, adrs += 0x20)
882 cinval((void *) adrs);
889 unsigned int instrs[2];
892 instrs[0] = 0x7c6002a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
893 instrs[1] = 0x4e800020;
895 store_inst(instrs+1);
896 code = (int (*)(void)) instrs;
901 write_spr(int n, unsigned int val)
903 unsigned int instrs[2];
904 int (*code)(unsigned int);
906 instrs[0] = 0x7c6003a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
907 instrs[1] = 0x4e800020;
909 store_inst(instrs+1);
910 code = (int (*)(unsigned int)) instrs;
914 static unsigned int regno;
915 extern char exc_prolog;
926 printf("msr = %x, pvr = %x\n", get_msr(), get_pvr());
927 printf("sprg0-3 = %x %x %x %x\n", get_sprg0(), get_sprg1(),
928 get_sprg2(), get_sprg3());
929 printf("srr0 = %x, srr1 = %x\n", get_srr0(), get_srr1());
930 #ifdef CONFIG_PPC_STD_MMU
932 for (i = 0; i < 16; ++i)
933 printf(" %x", get_sr(i));
936 asm("mr %0,1" : "=r" (i) :);
937 printf("sp = %x ", i);
938 asm("mr %0,2" : "=r" (i) :);
939 printf("toc = %x\n", i);
946 val = read_spr(regno);
948 write_spr(regno, val);
951 printf("spr %x = %x\n", regno, read_spr(regno));
967 #ifndef CONFIG_PPC_STD_MMU
969 dump_hash_table(void)
971 printf("This CPU doesn't have a hash table.\n");
976 dump_hash_table_seg(unsigned seg, unsigned start, unsigned end)
979 extern unsigned long Hash_size;
980 unsigned *htab = Hash;
981 unsigned hsize = Hash_size;
982 unsigned v, hmask, va, last_va = 0;
983 int found, last_found, i;
984 unsigned *hg, w1, last_w2 = 0, last_va0 = 0;
987 hmask = hsize / 64 - 1;
989 start = (start >> 12) & 0xffff;
990 end = (end >> 12) & 0xffff;
991 for (v = start; v < end; ++v) {
993 hg = htab + (((v ^ seg) & hmask) * 16);
994 w1 = 0x80000000 | (seg << 7) | (v >> 10);
995 for (i = 0; i < 8; ++i, hg += 2) {
1003 hg = htab + ((~(v ^ seg) & hmask) * 16);
1004 for (i = 0; i < 8; ++i, hg += 2) {
1011 if (!(last_found && found && (hg[1] & ~0x180) == last_w2 + 4096)) {
1013 if (last_va != last_va0)
1014 printf(" ... %x", last_va);
1018 printf("%x to %x", va, hg[1]);
1024 last_w2 = hg[1] & ~0x180;
1030 printf(" ... %x\n", last_va);
1033 static unsigned hash_ctx;
1034 static unsigned hash_start;
1035 static unsigned hash_end;
1038 dump_hash_table(void)
1041 unsigned seg_start, seg_end;
1045 hash_end = 0xfffff000;
1047 scanhex(&hash_start);
1049 printf("Mappings for context %x\n", hash_ctx);
1050 seg_start = hash_start;
1051 for (seg = hash_start >> 28; seg <= hash_end >> 28; ++seg) {
1052 seg_end = (seg << 28) | 0x0ffff000;
1053 if (seg_end > hash_end)
1055 dump_hash_table_seg((hash_ctx << 4) + (seg * 0x111),
1056 seg_start, seg_end);
1057 seg_start = seg_end + 0x1000;
1060 #endif /* CONFIG_PPC_STD_MMU */
1063 * Stuff for reading and writing memory safely
1067 mread(unsigned adrs, void *buf, int size)
1073 if( setjmp(bus_error_jmp) == 0 ){
1074 debugger_fault_handler = handle_fault;
1079 case 2: *(short *)q = *(short *)p; break;
1080 case 4: *(int *)q = *(int *)p; break;
1082 for( ; n < size; ++n ) {
1088 /* wait a little while to see if we get a machine check */
1092 debugger_fault_handler = NULL;
1097 mwrite(unsigned adrs, void *buf, int size)
1103 if( setjmp(bus_error_jmp) == 0 ){
1104 debugger_fault_handler = handle_fault;
1109 case 2: *(short *)p = *(short *)q; break;
1110 case 4: *(int *)p = *(int *)q; break;
1112 for( ; n < size; ++n ) {
1120 printf("*** Error writing address %x\n", adrs + n);
1122 debugger_fault_handler = NULL;
1126 static int fault_type;
1127 static int fault_except;
1128 static char *fault_chars[] = { "--", "**", "##" };
1131 handle_fault(struct pt_regs *regs)
1133 fault_except = TRAP(regs);
1134 fault_type = TRAP(regs) == 0x200? 0: TRAP(regs) == 0x300? 1: 2;
1135 longjmp(bus_error_jmp, 1);
1138 #define SWAP(a, b, t) ((t) = (a), (a) = (b), (b) = (t))
1141 byterev(unsigned char *val, int size)
1147 SWAP(val[0], val[1], t);
1150 SWAP(val[0], val[3], t);
1151 SWAP(val[1], val[2], t);
1162 int cmd, inc, i, nslash;
1164 unsigned char val[4];
1168 while ((cmd = skipbl()) != '\n') {
1170 case 'b': size = 1; break;
1171 case 'w': size = 2; break;
1172 case 'l': size = 4; break;
1173 case 'r': brev = !brev; break;
1174 case 'n': mnoread = 1; break;
1175 case '.': mnoread = 0; break;
1184 n = mread(adrs, val, size);
1185 printf("%.8x%c", adrs, brev? 'r': ' ');
1190 for (i = 0; i < n; ++i)
1191 printf("%.2x", val[i]);
1192 for (; i < size; ++i)
1193 printf("%s", fault_chars[fault_type]);
1200 for (i = 0; i < size; ++i)
1201 val[i] = n >> (i * 8);
1204 mwrite(adrs, val, size);
1217 else if( n == '\'' )
1219 for (i = 0; i < size; ++i)
1220 val[i] = n >> (i * 8);
1223 mwrite(adrs, val, size);
1257 adrs -= 1 << nslash;
1261 adrs += 1 << nslash;
1265 adrs += 1 << -nslash;
1269 adrs -= 1 << -nslash;
1303 case 'n': c = '\n'; break;
1304 case 'r': c = '\r'; break;
1305 case 'b': c = '\b'; break;
1306 case 't': c = '\t'; break;
1317 if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')
1326 adrs += ppc_inst_dump(adrs, nidump);
1332 prdump(adrs, ndump);
1339 prdump(unsigned adrs, int ndump)
1341 register int n, m, c, r, nr;
1342 unsigned char temp[16];
1344 for( n = ndump; n > 0; ){
1345 printf("%.8x", adrs);
1348 nr = mread(adrs, temp, r);
1350 for( m = 0; m < r; ++m ){
1351 putchar((m & 3) == 0 && m > 0? '.': ' ');
1353 printf("%.2x", temp[m]);
1355 printf("%s", fault_chars[fault_type]);
1360 for( m = 0; m < r; ++m ){
1363 putchar(' ' <= c && c <= '~'? c: '.');
1377 ppc_inst_dump(unsigned adr, int count)
1381 unsigned long inst, last_inst = 0;
1382 unsigned char val[4];
1385 for (first_adr = adr; count > 0; --count, adr += 4){
1386 nr = mread(adr, val, 4);
1388 const char *x = fault_chars[fault_type];
1389 printf("%.8x %s%s%s%s\n", adr, x, x, x, x);
1392 inst = GETWORD(val);
1393 if (adr > first_adr && inst == last_inst) {
1402 printf("%.8x ", adr);
1403 printf("%.8x\t", inst);
1404 print_insn_big_powerpc(stdout, inst, adr); /* always returns 4 */
1407 return adr - first_adr;
1411 print_address(unsigned addr)
1413 printf("0x%x", addr);
1417 * Memory operations - move, set, print differences
1419 static unsigned mdest; /* destination address */
1420 static unsigned msrc; /* source address */
1421 static unsigned mval; /* byte value to set memory to */
1422 static unsigned mcount; /* # bytes to affect */
1423 static unsigned mdiffs; /* max # differences to print */
1429 if( termch != '\n' )
1431 scanhex(cmd == 's'? &mval: &msrc);
1432 if( termch != '\n' )
1437 memmove((void *)mdest, (void *)msrc, mcount);
1440 memset((void *)mdest, mval, mcount);
1443 if( termch != '\n' )
1446 memdiffs((unsigned char *)mdest, (unsigned char *)msrc, mcount, mdiffs);
1452 memdiffs(unsigned char *p1, unsigned char *p2, unsigned nb, unsigned maxpr)
1457 for( n = nb; n > 0; --n )
1458 if( *p1++ != *p2++ )
1459 if( ++prt <= maxpr )
1460 printf("%.8x %.2x # %.8x %.2x\n", (unsigned)p1 - 1,
1461 p1[-1], (unsigned)p2 - 1, p2[-1]);
1463 printf("Total of %d differences\n", prt);
1466 static unsigned mend;
1467 static unsigned mask;
1473 unsigned char val[4];
1477 if (termch != '\n') {
1480 if (termch != '\n') {
1484 if (termch != '\n') termch = 0;
1489 for (a = mdest; a < mend; a += 4) {
1490 if (mread(a, val, 4) == 4
1491 && ((GETWORD(val) ^ mval) & mask) == 0) {
1492 printf("%.8x: %.8x\n", a, GETWORD(val));
1499 static unsigned mskip = 0x1000;
1500 static unsigned mlim = 0xffffffff;
1510 if (termch != '\n') termch = 0;
1512 if (termch != '\n') termch = 0;
1515 for (a = mdest; a < mlim; a += mskip) {
1516 ok = mread(a, &v, 1);
1518 printf("%.8x .. ", a);
1520 } else if (!ok && ook)
1521 printf("%.8x\n", a - mskip);
1527 printf("%.8x\n", a - mskip);
1532 unsigned int args[8];
1535 typedef unsigned int (*callfunc_t)(unsigned int, unsigned int,
1536 unsigned int, unsigned int, unsigned int,
1537 unsigned int, unsigned int, unsigned int);
1543 for (i = 0; i < 8; ++i)
1545 for (i = 0; i < 8; ++i) {
1546 if (!scanhex(&args[i]) || termch == '\n')
1550 func = (callfunc_t) adrs;
1552 if (setjmp(bus_error_jmp) == 0) {
1553 debugger_fault_handler = handle_fault;
1555 ret = func(args[0], args[1], args[2], args[3],
1556 args[4], args[5], args[6], args[7]);
1558 printf("return value is %x\n", ret);
1560 printf("*** %x exception occurred\n", fault_except);
1562 debugger_fault_handler = NULL;
1565 /* Input scanning routines */
1576 while( c == ' ' || c == '\t' )
1582 static char *regnames[N_PTREGS] = {
1583 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
1584 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
1585 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
1586 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
1587 "pc", "msr", "or3", "ctr", "lr", "xer", "ccr", "mq",
1588 "trap", "dar", "dsisr", "res"
1592 scanhex(unsigned *vp)
1599 /* parse register name */
1603 for (i = 0; i < sizeof(regname) - 1; ++i) {
1612 for (i = 0; i < N_PTREGS; ++i) {
1613 if (strcmp(regnames[i], regname) == 0) {
1614 unsigned *rp = (unsigned *)
1615 xmon_regs[smp_processor_id()];
1617 printf("regs not available\n");
1624 printf("invalid register name '%%%s'\n", regname);
1626 } else if (c == '$') {
1627 static char symname[128];
1629 for (i=0; i<63; i++) {
1639 if (setjmp(bus_error_jmp) == 0) {
1640 debugger_fault_handler = handle_fault;
1642 *vp = kallsyms_lookup_name(symname);
1645 debugger_fault_handler = NULL;
1647 printf("unknown symbol\n");
1663 } while( d != EOF );
1682 if( '0' <= c && c <= '9' )
1684 if( 'A' <= c && c <= 'F' )
1685 return c - ('A' - 10);
1686 if( 'a' <= c && c <= 'f' )
1687 return c - ('a' - 10);
1692 getstring(char *s, int size)
1703 } while( c != ' ' && c != '\t' && c != '\n' );
1708 static char line[256];
1709 static char *lineptr;
1720 if (lineptr == NULL || *lineptr == 0) {
1721 if (fgets(line, sizeof(line), stdin) == NULL) {
1731 take_input(char *str)
1739 int type = inchar();
1741 static char tmp[128];
1746 xmon_print_symbol(addr, ": ", "\n");
1751 if (setjmp(bus_error_jmp) == 0) {
1752 debugger_fault_handler = handle_fault;
1754 addr = kallsyms_lookup_name(tmp);
1756 printf("%s: %lx\n", tmp, addr);
1758 printf("Symbol '%s' not found.\n", tmp);
1761 debugger_fault_handler = NULL;