2 * Routines providing a simple monitor for use on the PowerMac.
4 * Copyright (C) 1996 Paul Mackerras.
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
11 #include <linux/config.h>
12 #include <linux/errno.h>
13 #include <linux/sched.h>
14 #include <linux/smp.h>
16 #include <linux/reboot.h>
17 #include <linux/delay.h>
18 #include <linux/kallsyms.h>
19 #include <linux/cpumask.h>
21 #include <asm/ptrace.h>
22 #include <asm/string.h>
24 #include <asm/machdep.h>
25 #include <asm/processor.h>
26 #include <asm/pgtable.h>
28 #include <asm/mmu_context.h>
31 #include <asm/ppcdebug.h>
32 #include <asm/cputable.h>
37 #define scanhex xmon_scanhex
38 #define skipbl xmon_skipbl
41 volatile cpumask_t cpus_in_xmon = CPU_MASK_NONE;
42 static unsigned long got_xmon = 0;
43 static volatile int take_xmon = -1;
44 static volatile int leaving_xmon = 0;
45 #endif /* CONFIG_SMP */
47 static unsigned long adrs;
49 static unsigned long ndump = 64;
50 static unsigned long nidump = 16;
51 static unsigned long ncsum = 4096;
53 static char tmpstr[128];
55 static u_int bus_error_jmp[100];
56 #define setjmp xmon_setjmp
57 #define longjmp xmon_longjmp
59 /* Breakpoint stuff */
61 unsigned long address;
64 unsigned char enabled;
68 static struct bpt bpts[NBPTS];
69 static struct bpt dabr;
70 static struct bpt iabr;
71 static unsigned bpinstr = 0x7fe00008; /* trap */
74 static int cmds(struct pt_regs *);
75 static int mread(unsigned long, void *, int);
76 static int mwrite(unsigned long, void *, int);
77 static int handle_fault(struct pt_regs *);
78 static void byterev(unsigned char *, int);
79 static void memex(void);
80 static int bsesc(void);
81 static void dump(void);
82 static void prdump(unsigned long, long);
83 static int ppc_inst_dump(unsigned long, long);
84 void print_address(unsigned long);
85 static void backtrace(struct pt_regs *);
86 static void excprint(struct pt_regs *);
87 static void prregs(struct pt_regs *);
88 static void memops(int);
89 static void memlocate(void);
90 static void memzcan(void);
91 static void memdiffs(unsigned char *, unsigned char *, unsigned, unsigned);
93 int scanhex(unsigned long *valp);
94 static void scannl(void);
95 static int hexdigit(int);
96 void getstring(char *, int);
97 static void flush_input(void);
98 static int inchar(void);
99 static void take_input(char *);
100 /* static void openforth(void); */
101 static unsigned long read_spr(int);
102 static void write_spr(int, unsigned long);
103 static void super_regs(void);
104 static void remove_bpts(void);
105 static void insert_bpts(void);
106 static struct bpt *at_breakpoint(unsigned long pc);
107 static void bpt_cmds(void);
108 static void cacheflush(void);
110 static void cpu_cmd(void);
111 #endif /* CONFIG_SMP */
112 static void csum(void);
113 static void bootcmds(void);
114 void dump_segments(void);
115 static void symbol_lookup(void);
117 static void debug_trace(void);
119 extern int print_insn_big_powerpc(FILE *, unsigned long, unsigned long);
120 extern void printf(const char *fmt, ...);
121 extern void xmon_vfprintf(void *f, const char *fmt, va_list ap);
122 extern int xmon_putc(int c, void *f);
123 extern int putchar(int ch);
124 extern int xmon_read_poll(void);
125 extern int setjmp(u_int *);
126 extern void longjmp(u_int *, int);
127 extern unsigned long _ASR;
129 pte_t *find_linux_pte(pgd_t *pgdir, unsigned long va); /* from htab.c */
131 #define GETWORD(v) (((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
133 #define isxdigit(c) (('0' <= (c) && (c) <= '9') \
134 || ('a' <= (c) && (c) <= 'f') \
135 || ('A' <= (c) && (c) <= 'F'))
136 #define isalnum(c) (('0' <= (c) && (c) <= '9') \
137 || ('a' <= (c) && (c) <= 'z') \
138 || ('A' <= (c) && (c) <= 'Z'))
139 #define isspace(c) (c == ' ' || c == '\t' || c == 10 || c == 13 || c == 0)
141 static char *help_string = "\
143 b show breakpoints\n\
144 bd set data breakpoint\n\
145 bi set instruction breakpoint\n\
146 bc clear breakpoint\n"
149 c print cpus stopped in xmon\n\
150 ci send xmon interrupt to all other cpus\n\
151 c# try to switch to cpu number h (in hex)\n"
156 di dump instructions\n\
157 df dump float values\n\
158 dd dump double values\n\
159 e print exception information\n\
161 la lookup symbol+offset of specified address\n\
162 ls lookup address of specified symbol\n\
163 m examine/change memory\n\
164 mm move a block of memory\n\
165 ms set a block of memory\n\
166 md compare two blocks of memory\n\
167 ml locate a block of memory\n\
168 mz zero a block of memory\n\
169 mi show information about memory allocation\n\
170 p show the task list\n\
173 S print special registers\n\
175 T Enable/Disable PPCDBG flags\n\
176 x exit monitor and recover\n\
177 X exit monitor and dont recover\n\
178 u dump segment table or SLB\n\
185 static int xmon_trace[NR_CPUS];
186 #define SSTEP 1 /* stepping because of 's' command */
187 #define BRSTEP 2 /* stepping over breakpoint */
189 static struct pt_regs *xmon_regs[NR_CPUS];
191 void __xmon_print_symbol(const char *fmt, unsigned long address);
192 #define xmon_print_symbol(fmt, addr) \
194 __check_printsym_format(fmt, ""); \
195 __xmon_print_symbol(fmt, addr); \
199 * Stuff for reading and writing memory safely
201 extern inline void sync(void)
203 asm volatile("sync; isync");
206 /* (Ref: 64-bit PowerPC ELF ABI Spplement; Ian Lance Taylor, Zembu Labs).
207 A PPC stack frame looks like this:
214 Parameter save area (SP+48)
215 TOC save area (SP+40)
216 link editor doubleword (SP+32)
217 compiler doubleword (SP+24)
222 Note that the LR (ret addr) may not be saved in the current frame if
223 no functions have been called from the current function.
226 #define SURVEILLANCE_TOKEN 9000
228 static inline void disable_surveillance(void)
230 #ifndef CONFIG_PPC_ISERIES
231 rtas_call(rtas_token("set-indicator"), 3, 1, NULL, SURVEILLANCE_TOKEN,
237 xmon(struct pt_regs *excp)
244 /* Ok, grab regs as they are now.
245 This won't do a particularily good job because the
246 prologue has already been executed.
247 ToDo: We could reach back into the callers save
248 area to do a better job of representing the
251 asm volatile ("std 0,0(%0)\n\
282 std 31,248(%0)" : : "b" (®s));
284 regs.nip = regs.link = ((unsigned long *)(regs.gpr[1]))[2];
285 regs.msr = get_msr();
286 regs.ctr = get_ctr();
287 regs.xer = get_xer();
294 set_msrd(msr & ~MSR_EE); /* disable interrupts */
295 xmon_regs[smp_processor_id()] = excp;
299 /* possible race condition here if a CPU is held up and gets
300 * here while we are exiting */
301 if (cpu_test_and_set(smp_processor_id(), cpus_in_xmon)) {
302 /* xmon probably caused an exception itself */
303 printf("We are already in xmon\n");
307 while (test_and_set_bit(0, &got_xmon)) {
308 if (take_xmon == smp_processor_id()) {
315 * XXX: breakpoints are removed while any cpu is in xmon
317 #endif /* CONFIG_SMP */
319 disable_surveillance();
320 printf("press ? for help ");
323 xmon_trace[smp_processor_id()] = SSTEP;
326 take_xmon = smp_processor_id();
328 } else if (at_breakpoint(excp->nip)) {
329 xmon_trace[smp_processor_id()] = BRSTEP;
332 xmon_trace[smp_processor_id()] = 0;
335 xmon_regs[smp_processor_id()] = 0;
339 clear_bit(0, &got_xmon);
340 cpu_clear(smp_processor_id(), cpus_in_xmon);
341 #endif /* CONFIG_SMP */
342 set_msrd(msr); /* restore interrupt enable */
351 xmon_bpt(struct pt_regs *regs)
355 bp = at_breakpoint(regs->nip);
362 xmon_trace[smp_processor_id()] = BRSTEP;
365 printf("Stopped at breakpoint %x (%lx ", (bp - bpts) + 1,
367 xmon_print_symbol("%s)\n", bp->address);
374 xmon_sstep(struct pt_regs *regs)
376 if (!xmon_trace[smp_processor_id()])
378 if (xmon_trace[smp_processor_id()] == BRSTEP) {
379 xmon_trace[smp_processor_id()] = 0;
388 xmon_dabr_match(struct pt_regs *regs)
390 if (dabr.enabled && dabr.count) {
394 xmon_trace[smp_processor_id()] = BRSTEP;
397 dabr.instr = regs->nip;
404 xmon_iabr_match(struct pt_regs *regs)
406 if (iabr.enabled && iabr.count) {
410 xmon_trace[smp_processor_id()] = BRSTEP;
419 at_breakpoint(unsigned long pc)
424 if (dabr.enabled && pc == dabr.instr)
426 if (iabr.enabled && pc == iabr.address)
429 for (i = 0; i < NBPTS; ++i, ++bp)
430 if (bp->enabled && pc == bp->address)
442 for (i = 0; i < NBPTS; ++i, ++bp) {
445 if (mread(bp->address, &bp->instr, 4) != 4
446 || mwrite(bp->address, &bpinstr, 4) != 4) {
447 printf("Couldn't insert breakpoint at %x, disabling\n",
451 store_inst((void *)bp->address);
456 set_dabr(dabr.address);
457 if ((cur_cpu_spec->cpu_features & CPU_FTR_IABR) && iabr.enabled)
458 set_iabr(iabr.address);
469 if ((cur_cpu_spec->cpu_features & CPU_FTR_IABR))
473 for (i = 0; i < NBPTS; ++i, ++bp) {
476 if (mread(bp->address, &instr, 4) == 4
478 && mwrite(bp->address, &bp->instr, 4) != 4)
479 printf("Couldn't remove breakpoint at %x\n",
482 store_inst((void *)bp->address);
486 static char *last_cmd;
488 /* Command interpreting routine */
490 cmds(struct pt_regs *excp)
497 /* Need to check if we should take any commands on
501 printf("%d:", smp_processor_id());
502 #endif /* CONFIG_SMP */
509 if (last_cmd == NULL)
511 take_input(last_cmd);
545 prregs(excp); /* print regs */
549 printf("No exception information\n");
583 #endif /* CONFIG_SMP */
593 printf("Unrecognized command: ");
595 if( ' ' < cmd && cmd <= '~' )
598 printf("\\x%x", cmd);
600 } while (cmd != '\n');
601 printf(" (type ? for help)\n");
608 static void bootcmds(void)
614 ppc_md.restart(NULL);
622 static void cpu_cmd(void)
630 printf("stopping all cpus\n");
631 /* interrupt other cpu(s) */
632 cpu = MSG_ALL_BUT_SELF;
633 smp_send_debugger_break(cpu);
637 if (!scanhex(&cpu)) {
638 /* print cpus waiting or in xmon */
639 printf("cpus stopped:");
640 for (cpu = 0; cpu < NR_CPUS; ++cpu) {
641 if (cpu_isset(cpu, cpus_in_xmon)) {
643 if (cpu == smp_processor_id())
650 /* try to switch to cpu specified */
653 while (take_xmon >= 0) {
654 if (--timeout == 0) {
655 /* yes there's a race here */
657 printf("cpu %u didn't take control\n", cpu);
661 /* now have to wait to be given control back */
662 while (test_and_set_bit(0, &got_xmon)) {
663 if (take_xmon == smp_processor_id()) {
670 #endif /* CONFIG_SMP */
672 static unsigned short fcstab[256] = {
673 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
674 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
675 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
676 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
677 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
678 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
679 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
680 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
681 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
682 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
683 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
684 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
685 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
686 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
687 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
688 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
689 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
690 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
691 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
692 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
693 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
694 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
695 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
696 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
697 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
698 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
699 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
700 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
701 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
702 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
703 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
704 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
707 #define FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
718 if (!scanhex(&ncsum))
721 for (i = 0; i < ncsum; ++i) {
722 if (mread(adrs+i, &v, 1) == 0) {
723 printf("csum stopped at %x\n", adrs+i);
731 static char *breakpoint_help_string =
732 "Breakpoint command usage:\n"
733 "b show breakpoints\n"
734 "b <addr> [cnt] set breakpoint at given instr addr\n"
735 "bc clear all breakpoints\n"
736 "bc <n/addr> clear breakpoint number n or at addr\n"
737 "bi <addr> [cnt] set hardware instr breakpoint (broken?)\n"
738 "bd <addr> [cnt] set hardware data breakpoint (broken?)\n"
751 case 'd': /* bd - hardware data breakpoint */
762 dabr.enabled = scanhex(&dabr.address);
763 scanhex(&dabr.count);
765 dabr.address = (dabr.address & ~7) | mode;
767 case 'i': /* bi - hardware instr breakpoint */
768 if (!(cur_cpu_spec->cpu_features & CPU_FTR_IABR)) {
769 printf("Not implemented on POWER4\n");
774 iabr.enabled = scanhex(&iabr.address);
777 scanhex(&iabr.count);
781 /* clear all breakpoints */
782 for (i = 0; i < NBPTS; ++i)
786 printf("All breakpoints cleared\n");
788 if (a <= NBPTS && a >= 1) {
789 /* assume a breakpoint number */
790 --a; /* bp nums are 1 based */
793 /* assume a breakpoint address */
794 bp = at_breakpoint(a);
797 printf("No breakpoint at %x\n", a);
799 printf("Cleared breakpoint %x (%lx ",
800 (bp - bpts) + 1, bp->address);
801 xmon_print_symbol("%s)\n", bp->address);
807 printf(breakpoint_help_string);
813 printf(breakpoint_help_string);
818 /* print all breakpoints */
821 printf(" type address count\n");
823 printf(" data %.16lx %8x [", dabr.address & ~7,
825 if (dabr.address & 1)
827 if (dabr.address & 2)
832 printf(" inst %.16lx %8x\n", iabr.address & ~3,
834 for (bp = bpts, bpnum = 1; bp < &bpts[NBPTS]; ++bp, ++bpnum)
836 printf("%2x trap %.16lx %8x ",
837 bpnum, bp->address, bp->count);
838 xmon_print_symbol("%s\n", bp->address);
843 if (systemcfg->platform != PLATFORM_POWERMAC &&
844 !(systemcfg->platform & PLATFORM_PSERIES)) {
845 printf("Not supported for this platform\n");
849 bp = at_breakpoint(a);
851 for (bp = bpts; bp < &bpts[NBPTS]; ++bp)
854 if (bp >= &bpts[NBPTS]) {
855 printf("Sorry, no free breakpoints. Please clear one first.\n");
863 printf("Set breakpoint %2x trap %.16lx %8x ", (bp-bpts) + 1,
864 bp->address, bp->count);
865 xmon_print_symbol("%s\n", bp->address);
870 /* Very cheap human name for vector lookup. */
872 const char *getvecname(unsigned long vec)
876 case 0x100: ret = "(System Reset)"; break;
877 case 0x200: ret = "(Machine Check)"; break;
878 case 0x300: ret = "(Data Access)"; break;
879 case 0x380: ret = "(Data SLB Access)"; break;
880 case 0x400: ret = "(Instruction Access)"; break;
881 case 0x480: ret = "(Instruction SLB Access)"; break;
882 case 0x500: ret = "(Hardware Interrupt)"; break;
883 case 0x600: ret = "(Alignment)"; break;
884 case 0x700: ret = "(Program Check)"; break;
885 case 0x800: ret = "(FPU Unavailable)"; break;
886 case 0x900: ret = "(Decrementer)"; break;
887 case 0xc00: ret = "(System Call)"; break;
888 case 0xd00: ret = "(Single Step)"; break;
889 case 0xf00: ret = "(Performance Monitor)"; break;
896 * Most of our exceptions are in the form:
898 * b .ret_from_exception
899 * and this currently fails to catch them.
901 static inline int exception_frame(unsigned long ip)
903 extern void *ret_from_syscall_1, *ret_from_syscall_2, *ret_from_except;
905 if ((ip == (unsigned long)ret_from_syscall_1) ||
906 (ip == (unsigned long)ret_from_syscall_2) ||
907 (ip == (unsigned long)ret_from_except))
913 static int xmon_depth_to_print = 64;
915 static void xmon_show_stack(unsigned long sp)
923 if (sp < PAGE_OFFSET) {
924 printf("SP in userspace\n");
928 if (!mread((sp + 16), &ip, sizeof(unsigned long)))
931 printf("[%016lx] [%016lx] ", sp, ip);
932 xmon_print_symbol("%s\n", ip);
934 if (exception_frame(ip)) {
935 if (mread(sp+112, ®s, sizeof(regs)) != sizeof(regs))
938 printf(" exception: %lx %s regs %lx\n", regs.trap,
939 getvecname(regs.trap), sp+112);
942 if (!mread(sp, &newsp, sizeof(unsigned long)))
948 } while (count++ < xmon_depth_to_print);
951 static void backtrace(struct pt_regs *excp)
966 spinlock_t exception_print_lock = SPIN_LOCK_UNLOCKED;
968 void excprint(struct pt_regs *fp)
972 spin_lock_irqsave(&exception_print_lock, flags);
975 printf("cpu %d: ", smp_processor_id());
976 #endif /* CONFIG_SMP */
978 printf("Vector: %lx %s at [%lx]\n", fp->trap, getvecname(fp->trap), fp);
979 printf(" pc: %lx", fp->nip);
980 xmon_print_symbol(" (%s)\n", fp->nip);
982 printf(" lr: %lx", fp->link);
983 xmon_print_symbol(" (%s)\n", fp->link);
985 printf(" sp: %lx\n", fp->gpr[1]);
986 printf(" msr: %lx\n", fp->msr);
988 if (fp->trap == 0x300 || fp->trap == 0x380 || fp->trap == 0x600) {
989 printf(" dar: %lx\n", fp->dar);
990 printf(" dsisr: %lx\n", fp->dsisr);
993 printf(" current = 0x%lx\n", current);
994 printf(" paca = 0x%lx\n", get_paca());
996 printf(" pid = %ld, comm = %s\n",
997 current->pid, current->comm);
1000 spin_unlock_irqrestore(&exception_print_lock, flags);
1003 void prregs(struct pt_regs *fp)
1008 if (scanhex((void *)&base))
1009 fp = (struct pt_regs *) base;
1011 if (setjmp(bus_error_jmp) == 0) {
1012 __debugger_fault_handler = handle_fault;
1014 for (n = 0; n < 16; ++n)
1015 printf("R%.2ld = %.16lx R%.2ld = %.16lx\n", n,
1016 fp->gpr[n], n+16, fp->gpr[n+16]);
1017 printf("pc = %.16lx msr = %.16lx\nlr = %.16lx "
1018 "cr = %.16lx\n", fp->nip, fp->msr, fp->link, fp->ccr);
1019 printf("ctr = %.16lx xer = %.16lx trap = %8lx\n",
1020 fp->ctr, fp->xer, fp->trap);
1023 /* wait a little while to see if we get a machine check */
1026 printf("*** Error reading regs\n");
1034 unsigned long nflush;
1039 scanhex((void *)&adrs);
1044 nflush = (nflush + L1_CACHE_BYTES - 1) / L1_CACHE_BYTES;
1045 if (setjmp(bus_error_jmp) == 0) {
1046 __debugger_fault_handler = handle_fault;
1050 for (; nflush > 0; --nflush, adrs += L1_CACHE_BYTES)
1051 cflush((void *) adrs);
1053 for (; nflush > 0; --nflush, adrs += L1_CACHE_BYTES)
1054 cinval((void *) adrs);
1057 /* wait a little while to see if we get a machine check */
1060 __debugger_fault_handler = 0;
1066 unsigned int instrs[2];
1067 unsigned long (*code)(void);
1068 unsigned long opd[3];
1069 unsigned long ret = -1UL;
1071 instrs[0] = 0x7c6002a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
1072 instrs[1] = 0x4e800020;
1073 opd[0] = (unsigned long)instrs;
1077 store_inst(instrs+1);
1078 code = (unsigned long (*)(void)) opd;
1080 if (setjmp(bus_error_jmp) == 0) {
1081 __debugger_fault_handler = handle_fault;
1087 /* wait a little while to see if we get a machine check */
1090 printf("*** Error reading spr %x\n", n);
1093 __debugger_fault_handler = 0;
1099 write_spr(int n, unsigned long val)
1101 unsigned int instrs[2];
1102 unsigned long (*code)(unsigned long);
1103 unsigned long opd[3];
1105 instrs[0] = 0x7c6003a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
1106 instrs[1] = 0x4e800020;
1107 opd[0] = (unsigned long)instrs;
1111 store_inst(instrs+1);
1112 code = (unsigned long (*)(unsigned long)) opd;
1114 if (setjmp(bus_error_jmp) == 0) {
1115 __debugger_fault_handler = handle_fault;
1121 /* wait a little while to see if we get a machine check */
1124 printf("*** Error writing spr %x\n", n);
1127 __debugger_fault_handler = 0;
1130 static unsigned long regno;
1131 extern char exc_prolog;
1132 extern char dec_exc;
1139 #ifdef CONFIG_PPC_ISERIES
1140 struct paca_struct *ptrPaca = NULL;
1141 struct ItLpPaca *ptrLpPaca = NULL;
1142 struct ItLpRegSave *ptrLpRegSave = NULL;
1147 unsigned long sp, toc;
1148 asm("mr %0,1" : "=r" (sp) :);
1149 asm("mr %0,2" : "=r" (toc) :);
1151 printf("msr = %.16lx sprg0= %.16lx\n", get_msr(), get_sprg0());
1152 printf("pvr = %.16lx sprg1= %.16lx\n", get_pvr(), get_sprg1());
1153 printf("dec = %.16lx sprg2= %.16lx\n", get_dec(), get_sprg2());
1154 printf("sp = %.16lx sprg3= %.16lx\n", sp, get_sprg3());
1155 printf("toc = %.16lx dar = %.16lx\n", toc, get_dar());
1156 printf("srr0 = %.16lx srr1 = %.16lx\n", get_srr0(), get_srr1());
1157 #ifdef CONFIG_PPC_ISERIES
1158 // Dump out relevant Paca data areas.
1160 ptrPaca = get_paca();
1162 printf(" Local Processor Control Area (LpPaca): \n");
1163 ptrLpPaca = ptrPaca->xLpPacaPtr;
1164 printf(" Saved Srr0=%.16lx Saved Srr1=%.16lx \n", ptrLpPaca->xSavedSrr0, ptrLpPaca->xSavedSrr1);
1165 printf(" Saved Gpr3=%.16lx Saved Gpr4=%.16lx \n", ptrLpPaca->xSavedGpr3, ptrLpPaca->xSavedGpr4);
1166 printf(" Saved Gpr5=%.16lx \n", ptrLpPaca->xSavedGpr5);
1168 printf(" Local Processor Register Save Area (LpRegSave): \n");
1169 ptrLpRegSave = ptrPaca->xLpRegSavePtr;
1170 printf(" Saved Sprg0=%.16lx Saved Sprg1=%.16lx \n", ptrLpRegSave->xSPRG0, ptrLpRegSave->xSPRG0);
1171 printf(" Saved Sprg2=%.16lx Saved Sprg3=%.16lx \n", ptrLpRegSave->xSPRG2, ptrLpRegSave->xSPRG3);
1172 printf(" Saved Msr =%.16lx Saved Nia =%.16lx \n", ptrLpRegSave->xMSR, ptrLpRegSave->xNIA);
1181 val = read_spr(regno);
1183 write_spr(regno, val);
1186 printf("spr %lx = %lx\n", regno, read_spr(regno));
1198 mread(unsigned long adrs, void *buf, int size)
1204 if (setjmp(bus_error_jmp) == 0) {
1205 __debugger_fault_handler = handle_fault;
1211 *(short *)q = *(short *)p;
1214 *(int *)q = *(int *)p;
1217 *(long *)q = *(long *)p;
1220 for( ; n < size; ++n) {
1226 /* wait a little while to see if we get a machine check */
1230 __debugger_fault_handler = 0;
1235 mwrite(unsigned long adrs, void *buf, int size)
1241 if (setjmp(bus_error_jmp) == 0) {
1242 __debugger_fault_handler = handle_fault;
1248 *(short *)p = *(short *)q;
1251 *(int *)p = *(int *)q;
1254 *(long *)p = *(long *)q;
1257 for ( ; n < size; ++n) {
1263 /* wait a little while to see if we get a machine check */
1267 printf("*** Error writing address %x\n", adrs + n);
1269 __debugger_fault_handler = 0;
1273 static int fault_type;
1274 static char *fault_chars[] = { "--", "**", "##" };
1277 handle_fault(struct pt_regs *regs)
1279 switch (regs->trap) {
1291 longjmp(bus_error_jmp, 1);
1296 #define SWAP(a, b, t) ((t) = (a), (a) = (b), (b) = (t))
1299 byterev(unsigned char *val, int size)
1305 SWAP(val[0], val[1], t);
1308 SWAP(val[0], val[3], t);
1309 SWAP(val[1], val[2], t);
1311 case 8: /* is there really any use for this? */
1312 SWAP(val[0], val[7], t);
1313 SWAP(val[1], val[6], t);
1314 SWAP(val[2], val[5], t);
1315 SWAP(val[3], val[4], t);
1323 static char *memex_help_string =
1324 "Memory examine command usage:\n"
1325 "m [addr] [flags] examine/change memory\n"
1326 " addr is optional. will start where left off.\n"
1327 " flags may include chars from this set:\n"
1328 " b modify by bytes (default)\n"
1329 " w modify by words (2 byte)\n"
1330 " l modify by longs (4 byte)\n"
1331 " d modify by doubleword (8 byte)\n"
1332 " r toggle reverse byte order mode\n"
1333 " n do not read memory (for i/o spaces)\n"
1334 " . ok to read (default)\n"
1335 "NOTE: flags are saved as defaults\n"
1338 static char *memex_subcmd_help_string =
1339 "Memory examine subcommands:\n"
1340 " hexval write this val to current location\n"
1341 " 'string' write chars from string to this location\n"
1342 " ' increment address\n"
1343 " ^ decrement address\n"
1344 " / increment addr by 0x10. //=0x100, ///=0x1000, etc\n"
1345 " \\ decrement addr by 0x10. \\\\=0x100, \\\\\\=0x1000, etc\n"
1346 " ` clear no-read flag\n"
1347 " ; stay at this addr\n"
1348 " v change to byte mode\n"
1349 " w change to word (2 byte) mode\n"
1350 " l change to long (4 byte) mode\n"
1351 " u change to doubleword (8 byte) mode\n"
1352 " m addr change current addr\n"
1353 " n toggle no-read flag\n"
1354 " r toggle byte reverse flag\n"
1355 " < count back up count bytes\n"
1356 " > count skip forward count bytes\n"
1357 " x exit this mode\n"
1363 int cmd, inc, i, nslash;
1365 unsigned char val[16];
1367 scanhex((void *)&adrs);
1370 printf(memex_help_string);
1376 while ((cmd = skipbl()) != '\n') {
1378 case 'b': size = 1; break;
1379 case 'w': size = 2; break;
1380 case 'l': size = 4; break;
1381 case 'd': size = 8; break;
1382 case 'r': brev = !brev; break;
1383 case 'n': mnoread = 1; break;
1384 case '.': mnoread = 0; break;
1393 n = mread(adrs, val, size);
1394 printf("%.16x%c", adrs, brev? 'r': ' ');
1399 for (i = 0; i < n; ++i)
1400 printf("%.2x", val[i]);
1401 for (; i < size; ++i)
1402 printf("%s", fault_chars[fault_type]);
1409 for (i = 0; i < size; ++i)
1410 val[i] = n >> (i * 8);
1413 mwrite(adrs, val, size);
1426 else if( n == '\'' )
1428 for (i = 0; i < size; ++i)
1429 val[i] = n >> (i * 8);
1432 mwrite(adrs, val, size);
1469 adrs -= 1 << nslash;
1473 adrs += 1 << nslash;
1477 adrs += 1 << -nslash;
1481 adrs -= 1 << -nslash;
1484 scanhex((void *)&adrs);
1503 printf(memex_subcmd_help_string);
1518 case 'n': c = '\n'; break;
1519 case 'r': c = '\r'; break;
1520 case 'b': c = '\b'; break;
1521 case 't': c = '\t'; break;
1526 #define isxdigit(c) (('0' <= (c) && (c) <= '9') \
1527 || ('a' <= (c) && (c) <= 'f') \
1528 || ('A' <= (c) && (c) <= 'F'))
1535 if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')
1537 scanhex((void *)&adrs);
1544 adrs += ppc_inst_dump(adrs, nidump);
1550 prdump(adrs, ndump);
1557 prdump(unsigned long adrs, long ndump)
1559 long n, m, c, r, nr;
1560 unsigned char temp[16];
1562 for( n = ndump; n > 0; ){
1563 printf("%.16lx", adrs);
1566 nr = mread(adrs, temp, r);
1568 for( m = 0; m < r; ++m ){
1569 if ((m & 7) == 0 && m > 0)
1572 printf("%.2x", temp[m]);
1574 printf("%s", fault_chars[fault_type]);
1579 for( m = 0; m < r; ++m ){
1582 putchar(' ' <= c && c <= '~'? c: '.');
1596 ppc_inst_dump(unsigned long adr, long count)
1599 unsigned long first_adr;
1600 unsigned long inst, last_inst;
1601 unsigned char val[4];
1604 for (first_adr = adr; count > 0; --count, adr += 4){
1605 nr = mread(adr, val, 4);
1607 const char *x = fault_chars[fault_type];
1608 printf("%.16lx %s%s%s%s\n", adr, x, x, x, x);
1611 inst = GETWORD(val);
1612 if (adr > first_adr && inst == last_inst) {
1621 printf("%.16lx ", adr);
1622 printf("%.8x\t", inst);
1623 print_insn_big_powerpc(stdout, inst, adr); /* always returns 4 */
1626 return adr - first_adr;
1630 print_address(unsigned long addr)
1636 name = kallsyms_lookup(addr, &size, &offset, &modname, tmpstr);
1640 printf("0x%lx\t# %s:%s+0x%lx", addr, modname, name, offset);
1642 printf("0x%lx\t# %s+0x%lx", addr, name, offset);
1644 printf("0x%lx", addr);
1649 * Memory operations - move, set, print differences
1651 static unsigned long mdest; /* destination address */
1652 static unsigned long msrc; /* source address */
1653 static unsigned long mval; /* byte value to set memory to */
1654 static unsigned long mcount; /* # bytes to affect */
1655 static unsigned long mdiffs; /* max # differences to print */
1660 scanhex((void *)&mdest);
1661 if( termch != '\n' )
1663 scanhex((void *)(cmd == 's'? &mval: &msrc));
1664 if( termch != '\n' )
1666 scanhex((void *)&mcount);
1669 memmove((void *)mdest, (void *)msrc, mcount);
1672 memset((void *)mdest, mval, mcount);
1675 if( termch != '\n' )
1677 scanhex((void *)&mdiffs);
1678 memdiffs((unsigned char *)mdest, (unsigned char *)msrc, mcount, mdiffs);
1684 memdiffs(unsigned char *p1, unsigned char *p2, unsigned nb, unsigned maxpr)
1689 for( n = nb; n > 0; --n )
1690 if( *p1++ != *p2++ )
1691 if( ++prt <= maxpr )
1692 printf("%.16x %.2x # %.16x %.2x\n", p1 - 1,
1693 p1[-1], p2 - 1, p2[-1]);
1695 printf("Total of %d differences\n", prt);
1698 static unsigned mend;
1699 static unsigned mask;
1705 unsigned char val[4];
1708 scanhex((void *)&mdest);
1709 if (termch != '\n') {
1711 scanhex((void *)&mend);
1712 if (termch != '\n') {
1714 scanhex((void *)&mval);
1716 if (termch != '\n') termch = 0;
1717 scanhex((void *)&mask);
1721 for (a = mdest; a < mend; a += 4) {
1722 if (mread(a, val, 4) == 4
1723 && ((GETWORD(val) ^ mval) & mask) == 0) {
1724 printf("%.16x: %.16x\n", a, GETWORD(val));
1731 static unsigned long mskip = 0x1000;
1732 static unsigned long mlim = 0xffffffff;
1742 if (termch != '\n') termch = 0;
1744 if (termch != '\n') termch = 0;
1747 for (a = mdest; a < mlim; a += mskip) {
1748 ok = mread(a, &v, 1);
1750 printf("%.8x .. ", a);
1752 } else if (!ok && ook)
1753 printf("%.8x\n", a - mskip);
1759 printf("%.8x\n", a - mskip);
1762 /* Input scanning routines */
1773 while( c == ' ' || c == '\t' )
1779 static char *regnames[N_PTREGS] = {
1780 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
1781 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
1782 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
1783 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
1784 "pc", "msr", "or3", "ctr", "lr", "xer", "ccr", "mq",
1785 "trap", "dar", "dsisr", "res"
1797 /* parse register name */
1801 for (i = 0; i < sizeof(regname) - 1; ++i) {
1810 for (i = 0; i < N_PTREGS; ++i) {
1811 if (strcmp(regnames[i], regname) == 0) {
1812 unsigned long *rp = (unsigned long *)
1813 xmon_regs[smp_processor_id()];
1815 printf("regs not available\n");
1822 printf("invalid register name '%%%s'\n", regname);
1826 /* skip leading "0x" if any */
1832 } else if (c == '$') {
1834 for (i=0; i<63; i++) {
1843 *vp = kallsyms_lookup_name(tmpstr);
1845 printf("unknown symbol '%s'\n", tmpstr);
1881 if( '0' <= c && c <= '9' )
1883 if( 'A' <= c && c <= 'F' )
1884 return c - ('A' - 10);
1885 if( 'a' <= c && c <= 'f' )
1886 return c - ('a' - 10);
1891 getstring(char *s, int size)
1902 } while( c != ' ' && c != '\t' && c != '\n' );
1907 static char line[256];
1908 static char *lineptr;
1919 if (lineptr == NULL || *lineptr == 0) {
1920 if (fgets(line, sizeof(line), stdin) == NULL) {
1940 int type = inchar();
1942 static char tmp[64];
1946 if (scanhex(&addr)) {
1947 printf("%lx: ", addr);
1948 xmon_print_symbol("%s\n", addr);
1954 if (setjmp(bus_error_jmp) == 0) {
1955 __debugger_fault_handler = handle_fault;
1957 addr = kallsyms_lookup_name(tmp);
1959 printf("%s: %lx\n", tmp, addr);
1961 printf("Symbol '%s' not found.\n", tmp);
1964 __debugger_fault_handler = 0;
1971 /* xmon version of __print_symbol */
1972 void __xmon_print_symbol(const char *fmt, unsigned long address)
1976 unsigned long offset, size;
1978 if (setjmp(bus_error_jmp) == 0) {
1979 __debugger_fault_handler = handle_fault;
1981 name = kallsyms_lookup(address, &size, &offset, &modname,
1984 /* wait a little while to see if we get a machine check */
1987 name = "symbol lookup failed";
1990 __debugger_fault_handler = 0;
1993 char addrstr[sizeof("0x%lx") + (BITS_PER_LONG*3/10)];
1995 sprintf(addrstr, "0x%lx", address);
1996 printf(fmt, addrstr);
2001 /* This is pretty small. */
2002 char buffer[sizeof("%s+%#lx/%#lx [%s]")
2003 + strlen(name) + 2*(BITS_PER_LONG*3/10)
2006 sprintf(buffer, "%s+%#lx/%#lx [%s]",
2007 name, offset, size, modname);
2008 printf(fmt, buffer);
2010 char buffer[sizeof("%s+%#lx/%#lx")
2011 + strlen(name) + 2*(BITS_PER_LONG*3/10)];
2013 sprintf(buffer, "%s+%#lx/%#lx", name, offset, size);
2014 printf(fmt, buffer);
2018 static void debug_trace(void)
2020 unsigned long val, cmd, on;
2024 /* show current state */
2026 printf("naca->debug_switch = 0x%lx\n", naca->debug_switch);
2027 for (i = 0; i < PPCDBG_NUM_FLAGS ;i++) {
2028 on = PPCDBG_BITVAL(i) & naca->debug_switch;
2029 printf("%02x %s %12s ", i, on ? "on " : "off", trace_names[i] ? trace_names[i] : "");
2030 if (((i+1) % 3) == 0)
2036 while (cmd != '\n') {
2037 on = 1; /* default if no sign given */
2038 while (cmd == '+' || cmd == '-') {
2041 if (cmd == ' ' || cmd == '\n') { /* Turn on or off based on + or - */
2042 naca->debug_switch = on ? PPCDBG_ALL:PPCDBG_NONE;
2043 printf("Setting all values to %s...\n", on ? "on" : "off");
2044 if (cmd == '\n') return;
2045 else cmd = skipbl();
2050 termch = cmd; /* not +/- ... let scanhex see it */
2051 scanhex((void *)&val);
2053 printf("Value %x out of range:\n", val);
2057 naca->debug_switch |= PPCDBG_BITVAL(val);
2058 printf("enable debug %x %s\n", val, trace_names[val] ? trace_names[val] : "");
2060 naca->debug_switch &= ~PPCDBG_BITVAL(val);
2061 printf("disable debug %x %s\n", val, trace_names[val] ? trace_names[val] : "");
2067 static void dump_slb(void)
2072 printf("SLB contents of cpu %d\n", smp_processor_id());
2074 for (i = 0; i < naca->slb_size; i++) {
2075 asm volatile("slbmfee %0,%1" : "=r" (tmp) : "r" (i));
2076 printf("%02d %016lx ", i, tmp);
2078 asm volatile("slbmfev %0,%1" : "=r" (tmp) : "r" (i));
2079 printf("%016lx\n", tmp);
2083 static void dump_stab(void)
2086 unsigned long *tmp = (unsigned long *)get_paca()->xStab_data.virt;
2088 printf("Segment table contents of cpu %d\n", smp_processor_id());
2090 for (i = 0; i < PAGE_SIZE/16; i++) {
2097 printf("%03d %016lx ", i, a);
2098 printf("%016lx\n", b);
2103 void xmon_init(void)
2106 __debugger_bpt = xmon_bpt;
2107 __debugger_sstep = xmon_sstep;
2108 __debugger_iabr_match = xmon_iabr_match;
2109 __debugger_dabr_match = xmon_dabr_match;
2112 void dump_segments(void)
2114 if (cur_cpu_spec->cpu_features & CPU_FTR_SLB)