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 */
157 #define MSR_SSTEP_ENABLE 0x200
159 #define MSR_SSTEP_ENABLE 0x400
162 static struct pt_regs *xmon_regs[NR_CPUS];
164 extern inline void sync(void)
166 asm volatile("sync; isync");
169 extern inline void __delay(unsigned int loops)
172 __asm__ __volatile__("mtctr %0; 1: bdnz 1b" : :
173 "r" (loops) : "ctr");
176 /* Print an address in numeric and symbolic form (if possible) */
177 static void xmon_print_symbol(unsigned long address, const char *mid,
181 const char *name = NULL;
182 unsigned long offset, size;
183 static char tmpstr[128];
185 printf("%.8lx", address);
186 if (setjmp(bus_error_jmp) == 0) {
187 debugger_fault_handler = handle_fault;
189 name = kallsyms_lookup(address, &size, &offset, &modname,
192 /* wait a little while to see if we get a machine check */
195 debugger_fault_handler = NULL;
198 printf("%s%s+%#lx/%#lx", mid, name, offset, size);
200 printf(" [%s]", modname);
205 static void get_tb(unsigned *p)
207 unsigned hi, lo, hiagain;
209 if ((get_pvr() >> 16) == 1)
213 asm volatile("mftbu %0; mftb %1; mftbu %2"
214 : "=r" (hi), "=r" (lo), "=r" (hiagain));
215 } while (hi != hiagain);
220 static inline void xmon_enable_sstep(struct pt_regs *regs)
222 regs->msr |= MSR_SSTEP_ENABLE;
224 mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) | DBCR0_IC | DBCR0_IDM);
228 int xmon(struct pt_regs *excp)
233 get_tb(stop_tb[smp_processor_id()]);
235 asm volatile ("stw 0,0(%0)\n\
238 stmw 2,8(%0)" : : "b" (®s));
239 regs.nip = regs.link = ((unsigned long *)regs.gpr[1])[1];
240 regs.msr = get_msr();
241 regs.ctr = get_ctr();
242 regs.xer = get_xer();
249 set_msr(msr & ~0x8000); /* disable interrupts */
250 xmon_regs[smp_processor_id()] = excp;
254 if (test_and_set_bit(smp_processor_id(), &cpus_in_xmon))
257 while (test_and_set_bit(0, &got_xmon)) {
258 if (take_xmon == smp_processor_id()) {
264 * XXX: breakpoints are removed while any cpu is in xmon
266 #endif /* CONFIG_SMP */
270 xmon_trace[smp_processor_id()] = SSTEP;
271 xmon_enable_sstep(excp);
272 } else if (at_breakpoint(excp->nip)) {
273 xmon_trace[smp_processor_id()] = BRSTEP;
274 xmon_enable_sstep(excp);
276 xmon_trace[smp_processor_id()] = 0;
280 xmon_regs[smp_processor_id()] = NULL;
282 clear_bit(0, &got_xmon);
283 clear_bit(smp_processor_id(), &cpus_in_xmon);
284 #endif /* CONFIG_SMP */
285 set_msr(msr); /* restore interrupt enable */
286 get_tb(start_tb[smp_processor_id()]);
292 xmon_irq(int irq, void *d, struct pt_regs *regs)
295 local_irq_save(flags);
296 printf("Keyboard interrupt\n");
298 local_irq_restore(flags);
303 xmon_bpt(struct pt_regs *regs)
307 bp = at_breakpoint(regs->nip);
314 xmon_trace[smp_processor_id()] = BRSTEP;
315 xmon_enable_sstep(regs);
323 xmon_sstep(struct pt_regs *regs)
325 if (!xmon_trace[smp_processor_id()])
327 if (xmon_trace[smp_processor_id()] == BRSTEP) {
328 xmon_trace[smp_processor_id()] = 0;
337 xmon_dabr_match(struct pt_regs *regs)
339 if (dabr.enabled && dabr.count) {
343 xmon_trace[smp_processor_id()] = BRSTEP;
346 dabr.instr = regs->nip;
353 xmon_iabr_match(struct pt_regs *regs)
355 if (iabr.enabled && iabr.count) {
359 xmon_trace[smp_processor_id()] = BRSTEP;
368 at_breakpoint(unsigned pc)
373 if (dabr.enabled && pc == dabr.instr)
375 if (iabr.enabled && pc == iabr.address)
378 for (i = 0; i < NBPTS; ++i, ++bp)
379 if (bp->enabled && pc == bp->address)
391 for (i = 0; i < NBPTS; ++i, ++bp) {
394 if (mread(bp->address, &bp->instr, 4) != 4
395 || mwrite(bp->address, &bpinstr, 4) != 4) {
396 printf("Couldn't insert breakpoint at %x, disabling\n",
400 store_inst((void *) bp->address);
402 #if ! (defined(CONFIG_8xx) || defined(CONFIG_4xx))
404 set_dabr(dabr.address);
406 set_iabr(iabr.address);
417 #if ! (defined(CONFIG_8xx) || defined(CONFIG_4xx))
422 for (i = 0; i < NBPTS; ++i, ++bp) {
425 if (mread(bp->address, &instr, 4) == 4
427 && mwrite(bp->address, &bp->instr, 4) != 4)
428 printf("Couldn't remove breakpoint at %x\n",
430 store_inst((void *) bp->address);
434 static char *last_cmd;
436 /* Command interpreting routine */
438 cmds(struct pt_regs *excp)
445 printf("%d:", smp_processor_id());
446 #endif /* CONFIG_SMP */
453 if (last_cmd == NULL)
455 take_input(last_cmd);
487 prregs(excp); /* print regs */
491 printf("No exception information\n");
515 printf("Unrecognized command: ");
516 if( ' ' < cmd && cmd <= '~' )
519 printf("\\x%x", cmd);
520 printf(" (type ? for help)\n");
532 #endif /* CONFIG_SMP */
546 extern unsigned tb_to_us;
548 #define mulhwu(x,y) \
549 ({unsigned z; asm ("mulhwu %0,%1,%2" : "=r" (z) : "r" (x), "r" (y)); z;})
551 static void printtime(void)
555 delta = stop_tb[smp_processor_id()][1]
556 - start_tb[smp_processor_id()][1];
557 delta = mulhwu(tb_to_us, delta);
558 printf("%u.%06u seconds\n", delta / 1000000, delta % 1000000);
561 static void bootcmds(void)
567 ppc_md.restart(NULL);
575 static void cpu_cmd(void)
583 /* interrupt other cpu(s) */
584 cpu = MSG_ALL_BUT_SELF;
586 smp_send_xmon_break(cpu);
590 if (!scanhex(&cpu)) {
591 /* print cpus waiting or in xmon */
592 printf("cpus stopped:");
593 for (cpu = 0; cpu < NR_CPUS; ++cpu) {
594 if (test_bit(cpu, &cpus_in_xmon)) {
596 if (cpu == smp_processor_id())
603 /* try to switch to cpu specified */
606 while (take_xmon >= 0) {
607 if (--timeout == 0) {
608 /* yes there's a race here */
610 printf("cpu %u didn't take control\n", cpu);
614 /* now have to wait to be given control back */
615 while (test_and_set_bit(0, &got_xmon)) {
616 if (take_xmon == smp_processor_id()) {
622 #endif /* CONFIG_SMP */
625 static unsigned short fcstab[256] = {
626 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
627 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
628 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
629 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
630 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
631 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
632 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
633 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
634 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
635 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
636 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
637 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
638 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
639 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
640 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
641 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
642 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
643 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
644 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
645 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
646 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
647 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
648 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
649 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
650 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
651 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
652 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
653 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
654 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
655 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
656 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
657 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
660 #define FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
671 if (!scanhex(&ncsum))
674 for (i = 0; i < ncsum; ++i) {
675 if (mread(adrs+i, &v, 1) == 0) {
676 printf("csum stopped at %x\n", adrs+i);
694 #if ! (defined(CONFIG_8xx) || defined(CONFIG_4xx))
711 dabr.enabled = scanhex(&dabr.address);
712 scanhex(&dabr.count);
714 dabr.address = (dabr.address & ~7) | mode;
724 iabr.enabled = scanhex(&iabr.address);
726 iabr.address |= mode;
727 scanhex(&iabr.count);
732 /* clear all breakpoints */
733 for (i = 0; i < NBPTS; ++i)
737 printf("All breakpoints cleared\n");
739 bp = at_breakpoint(a);
741 printf("No breakpoint at %x\n", a);
750 /* print all breakpoints */
751 printf("type address count\n");
753 printf("data %.8x %8x [", dabr.address & ~7,
755 if (dabr.address & 1)
757 if (dabr.address & 2)
759 if (!(dabr.address & 4))
764 printf("inst %.8x %8x\n", iabr.address & ~3,
766 for (bp = bpts; bp < &bpts[NBPTS]; ++bp)
768 printf("trap %.8x %8x\n", bp->address,
772 bp = at_breakpoint(a);
774 for (bp = bpts; bp < &bpts[NBPTS]; ++bp)
777 if (bp >= &bpts[NBPTS]) {
778 printf("Sorry, no free breakpoints\n");
791 backtrace(struct pt_regs *excp)
796 extern char ret_from_except, ret_from_except_full, ret_from_syscall;
798 printf("backtrace:\n");
806 for (; sp != 0; sp = stack[0]) {
807 if (mread(sp, stack, sizeof(stack)) != sizeof(stack))
809 printf("[%.8lx] ", stack[0]);
810 xmon_print_symbol(stack[1], " ", "\n");
811 if (stack[1] == (unsigned) &ret_from_except
812 || stack[1] == (unsigned) &ret_from_except_full
813 || stack[1] == (unsigned) &ret_from_syscall) {
814 if (mread(sp+16, ®s, sizeof(regs)) != sizeof(regs))
816 printf("exception:%x [%x] %x\n", regs.trap, sp+16,
819 if (mread(sp, stack, sizeof(stack)) != sizeof(stack))
830 asm("mr %0,1" : "=r" (x) :);
835 excprint(struct pt_regs *fp)
840 printf("cpu %d: ", smp_processor_id());
841 #endif /* CONFIG_SMP */
842 printf("vector: %x at pc=", fp->trap);
843 xmon_print_symbol(fp->nip, ": ", ", lr=");
844 xmon_print_symbol(fp->link, ": ", "\n");
845 printf("msr = %x, sp = %x [%x]\n", fp->msr, fp->gpr[1], fp);
847 if (trap == 0x300 || trap == 0x600)
848 printf("dar = %x, dsisr = %x\n", fp->dar, fp->dsisr);
850 printf("current = %x, pid = %d, comm = %s\n",
851 current, current->pid, current->comm);
855 prregs(struct pt_regs *fp)
861 fp = (struct pt_regs *) base;
862 for (n = 0; n < 32; ++n) {
863 printf("R%.2d = %.8x%s", n, fp->gpr[n],
864 (n & 3) == 3? "\n": " ");
865 if (n == 12 && !FULL_REGS(fp)) {
870 printf("pc = %.8x msr = %.8x lr = %.8x cr = %.8x\n",
871 fp->nip, fp->msr, fp->link, fp->ccr);
872 printf("ctr = %.8x xer = %.8x trap = %4x\n",
873 fp->ctr, fp->xer, fp->trap);
890 nflush = (nflush + 31) / 32;
892 for (; nflush > 0; --nflush, adrs += 0x20)
893 cflush((void *) adrs);
895 for (; nflush > 0; --nflush, adrs += 0x20)
896 cinval((void *) adrs);
903 unsigned int instrs[2];
906 instrs[0] = 0x7c6002a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
907 instrs[1] = 0x4e800020;
909 store_inst(instrs+1);
910 code = (int (*)(void)) instrs;
915 write_spr(int n, unsigned int val)
917 unsigned int instrs[2];
918 int (*code)(unsigned int);
920 instrs[0] = 0x7c6003a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
921 instrs[1] = 0x4e800020;
923 store_inst(instrs+1);
924 code = (int (*)(unsigned int)) instrs;
928 static unsigned int regno;
929 extern char exc_prolog;
940 printf("msr = %x, pvr = %x\n", get_msr(), get_pvr());
941 printf("sprg0-3 = %x %x %x %x\n", get_sprg0(), get_sprg1(),
942 get_sprg2(), get_sprg3());
943 printf("srr0 = %x, srr1 = %x\n", get_srr0(), get_srr1());
944 #ifdef CONFIG_PPC_STD_MMU
946 for (i = 0; i < 16; ++i)
947 printf(" %x", get_sr(i));
950 asm("mr %0,1" : "=r" (i) :);
951 printf("sp = %x ", i);
952 asm("mr %0,2" : "=r" (i) :);
953 printf("toc = %x\n", i);
960 val = read_spr(regno);
962 write_spr(regno, val);
965 printf("spr %x = %x\n", regno, read_spr(regno));
981 #ifndef CONFIG_PPC_STD_MMU
983 dump_hash_table(void)
985 printf("This CPU doesn't have a hash table.\n");
990 dump_hash_table_seg(unsigned seg, unsigned start, unsigned end)
993 extern unsigned long Hash_size;
994 unsigned *htab = Hash;
995 unsigned hsize = Hash_size;
996 unsigned v, hmask, va, last_va = 0;
997 int found, last_found, i;
998 unsigned *hg, w1, last_w2 = 0, last_va0 = 0;
1001 hmask = hsize / 64 - 1;
1003 start = (start >> 12) & 0xffff;
1004 end = (end >> 12) & 0xffff;
1005 for (v = start; v < end; ++v) {
1007 hg = htab + (((v ^ seg) & hmask) * 16);
1008 w1 = 0x80000000 | (seg << 7) | (v >> 10);
1009 for (i = 0; i < 8; ++i, hg += 2) {
1017 hg = htab + ((~(v ^ seg) & hmask) * 16);
1018 for (i = 0; i < 8; ++i, hg += 2) {
1025 if (!(last_found && found && (hg[1] & ~0x180) == last_w2 + 4096)) {
1027 if (last_va != last_va0)
1028 printf(" ... %x", last_va);
1032 printf("%x to %x", va, hg[1]);
1038 last_w2 = hg[1] & ~0x180;
1044 printf(" ... %x\n", last_va);
1047 static unsigned hash_ctx;
1048 static unsigned hash_start;
1049 static unsigned hash_end;
1052 dump_hash_table(void)
1055 unsigned seg_start, seg_end;
1059 hash_end = 0xfffff000;
1061 scanhex(&hash_start);
1063 printf("Mappings for context %x\n", hash_ctx);
1064 seg_start = hash_start;
1065 for (seg = hash_start >> 28; seg <= hash_end >> 28; ++seg) {
1066 seg_end = (seg << 28) | 0x0ffff000;
1067 if (seg_end > hash_end)
1069 dump_hash_table_seg((hash_ctx << 4) + (seg * 0x111),
1070 seg_start, seg_end);
1071 seg_start = seg_end + 0x1000;
1074 #endif /* CONFIG_PPC_STD_MMU */
1077 * Stuff for reading and writing memory safely
1081 mread(unsigned adrs, void *buf, int size)
1087 if( setjmp(bus_error_jmp) == 0 ){
1088 debugger_fault_handler = handle_fault;
1093 case 2: *(short *)q = *(short *)p; break;
1094 case 4: *(int *)q = *(int *)p; break;
1096 for( ; n < size; ++n ) {
1102 /* wait a little while to see if we get a machine check */
1106 debugger_fault_handler = NULL;
1111 mwrite(unsigned adrs, void *buf, int size)
1117 if( setjmp(bus_error_jmp) == 0 ){
1118 debugger_fault_handler = handle_fault;
1123 case 2: *(short *)p = *(short *)q; break;
1124 case 4: *(int *)p = *(int *)q; break;
1126 for( ; n < size; ++n ) {
1134 printf("*** Error writing address %x\n", adrs + n);
1136 debugger_fault_handler = NULL;
1140 static int fault_type;
1141 static int fault_except;
1142 static char *fault_chars[] = { "--", "**", "##" };
1145 handle_fault(struct pt_regs *regs)
1147 fault_except = TRAP(regs);
1148 fault_type = TRAP(regs) == 0x200? 0: TRAP(regs) == 0x300? 1: 2;
1149 longjmp(bus_error_jmp, 1);
1152 #define SWAP(a, b, t) ((t) = (a), (a) = (b), (b) = (t))
1155 byterev(unsigned char *val, int size)
1161 SWAP(val[0], val[1], t);
1164 SWAP(val[0], val[3], t);
1165 SWAP(val[1], val[2], t);
1176 int cmd, inc, i, nslash;
1178 unsigned char val[4];
1182 while ((cmd = skipbl()) != '\n') {
1184 case 'b': size = 1; break;
1185 case 'w': size = 2; break;
1186 case 'l': size = 4; break;
1187 case 'r': brev = !brev; break;
1188 case 'n': mnoread = 1; break;
1189 case '.': mnoread = 0; break;
1198 n = mread(adrs, val, size);
1199 printf("%.8x%c", adrs, brev? 'r': ' ');
1204 for (i = 0; i < n; ++i)
1205 printf("%.2x", val[i]);
1206 for (; i < size; ++i)
1207 printf("%s", fault_chars[fault_type]);
1214 for (i = 0; i < size; ++i)
1215 val[i] = n >> (i * 8);
1218 mwrite(adrs, val, size);
1231 else if( n == '\'' )
1233 for (i = 0; i < size; ++i)
1234 val[i] = n >> (i * 8);
1237 mwrite(adrs, val, size);
1271 adrs -= 1 << nslash;
1275 adrs += 1 << nslash;
1279 adrs += 1 << -nslash;
1283 adrs -= 1 << -nslash;
1317 case 'n': c = '\n'; break;
1318 case 'r': c = '\r'; break;
1319 case 'b': c = '\b'; break;
1320 case 't': c = '\t'; break;
1331 if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')
1340 adrs += ppc_inst_dump(adrs, nidump);
1346 prdump(adrs, ndump);
1353 prdump(unsigned adrs, int ndump)
1355 register int n, m, c, r, nr;
1356 unsigned char temp[16];
1358 for( n = ndump; n > 0; ){
1359 printf("%.8x", adrs);
1362 nr = mread(adrs, temp, r);
1364 for( m = 0; m < r; ++m ){
1365 putchar((m & 3) == 0 && m > 0? '.': ' ');
1367 printf("%.2x", temp[m]);
1369 printf("%s", fault_chars[fault_type]);
1374 for( m = 0; m < r; ++m ){
1377 putchar(' ' <= c && c <= '~'? c: '.');
1391 ppc_inst_dump(unsigned adr, int count)
1395 unsigned long inst, last_inst = 0;
1396 unsigned char val[4];
1399 for (first_adr = adr; count > 0; --count, adr += 4){
1400 nr = mread(adr, val, 4);
1402 const char *x = fault_chars[fault_type];
1403 printf("%.8x %s%s%s%s\n", adr, x, x, x, x);
1406 inst = GETWORD(val);
1407 if (adr > first_adr && inst == last_inst) {
1416 printf("%.8x ", adr);
1417 printf("%.8x\t", inst);
1418 print_insn_big_powerpc(stdout, inst, adr); /* always returns 4 */
1421 return adr - first_adr;
1425 print_address(unsigned addr)
1427 printf("0x%x", addr);
1431 * Memory operations - move, set, print differences
1433 static unsigned mdest; /* destination address */
1434 static unsigned msrc; /* source address */
1435 static unsigned mval; /* byte value to set memory to */
1436 static unsigned mcount; /* # bytes to affect */
1437 static unsigned mdiffs; /* max # differences to print */
1443 if( termch != '\n' )
1445 scanhex(cmd == 's'? &mval: &msrc);
1446 if( termch != '\n' )
1451 memmove((void *)mdest, (void *)msrc, mcount);
1454 memset((void *)mdest, mval, mcount);
1457 if( termch != '\n' )
1460 memdiffs((unsigned char *)mdest, (unsigned char *)msrc, mcount, mdiffs);
1466 memdiffs(unsigned char *p1, unsigned char *p2, unsigned nb, unsigned maxpr)
1471 for( n = nb; n > 0; --n )
1472 if( *p1++ != *p2++ )
1473 if( ++prt <= maxpr )
1474 printf("%.8x %.2x # %.8x %.2x\n", (unsigned)p1 - 1,
1475 p1[-1], (unsigned)p2 - 1, p2[-1]);
1477 printf("Total of %d differences\n", prt);
1480 static unsigned mend;
1481 static unsigned mask;
1487 unsigned char val[4];
1491 if (termch != '\n') {
1494 if (termch != '\n') {
1498 if (termch != '\n') termch = 0;
1503 for (a = mdest; a < mend; a += 4) {
1504 if (mread(a, val, 4) == 4
1505 && ((GETWORD(val) ^ mval) & mask) == 0) {
1506 printf("%.8x: %.8x\n", a, GETWORD(val));
1513 static unsigned mskip = 0x1000;
1514 static unsigned mlim = 0xffffffff;
1524 if (termch != '\n') termch = 0;
1526 if (termch != '\n') termch = 0;
1529 for (a = mdest; a < mlim; a += mskip) {
1530 ok = mread(a, &v, 1);
1532 printf("%.8x .. ", a);
1534 } else if (!ok && ook)
1535 printf("%.8x\n", a - mskip);
1541 printf("%.8x\n", a - mskip);
1546 unsigned int args[8];
1549 typedef unsigned int (*callfunc_t)(unsigned int, unsigned int,
1550 unsigned int, unsigned int, unsigned int,
1551 unsigned int, unsigned int, unsigned int);
1557 for (i = 0; i < 8; ++i)
1559 for (i = 0; i < 8; ++i) {
1560 if (!scanhex(&args[i]) || termch == '\n')
1564 func = (callfunc_t) adrs;
1566 if (setjmp(bus_error_jmp) == 0) {
1567 debugger_fault_handler = handle_fault;
1569 ret = func(args[0], args[1], args[2], args[3],
1570 args[4], args[5], args[6], args[7]);
1572 printf("return value is %x\n", ret);
1574 printf("*** %x exception occurred\n", fault_except);
1576 debugger_fault_handler = NULL;
1579 /* Input scanning routines */
1590 while( c == ' ' || c == '\t' )
1596 static char *regnames[N_PTREGS] = {
1597 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
1598 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
1599 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
1600 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
1601 "pc", "msr", "or3", "ctr", "lr", "xer", "ccr", "mq",
1602 "trap", "dar", "dsisr", "res"
1606 scanhex(unsigned *vp)
1613 /* parse register name */
1617 for (i = 0; i < sizeof(regname) - 1; ++i) {
1626 for (i = 0; i < N_PTREGS; ++i) {
1627 if (strcmp(regnames[i], regname) == 0) {
1628 unsigned *rp = (unsigned *)
1629 xmon_regs[smp_processor_id()];
1631 printf("regs not available\n");
1638 printf("invalid register name '%%%s'\n", regname);
1640 } else if (c == '$') {
1641 static char symname[128];
1643 for (i=0; i<63; i++) {
1653 if (setjmp(bus_error_jmp) == 0) {
1654 debugger_fault_handler = handle_fault;
1656 *vp = kallsyms_lookup_name(symname);
1659 debugger_fault_handler = NULL;
1661 printf("unknown symbol\n");
1677 } while( d != EOF );
1696 if( '0' <= c && c <= '9' )
1698 if( 'A' <= c && c <= 'F' )
1699 return c - ('A' - 10);
1700 if( 'a' <= c && c <= 'f' )
1701 return c - ('a' - 10);
1706 getstring(char *s, int size)
1717 } while( c != ' ' && c != '\t' && c != '\n' );
1722 static char line[256];
1723 static char *lineptr;
1734 if (lineptr == NULL || *lineptr == 0) {
1735 if (fgets(line, sizeof(line), stdin) == NULL) {
1745 take_input(char *str)
1753 int type = inchar();
1755 static char tmp[128];
1760 xmon_print_symbol(addr, ": ", "\n");
1765 if (setjmp(bus_error_jmp) == 0) {
1766 debugger_fault_handler = handle_fault;
1768 addr = kallsyms_lookup_name(tmp);
1770 printf("%s: %lx\n", tmp, addr);
1772 printf("Symbol '%s' not found.\n", tmp);
1775 debugger_fault_handler = NULL;